# The No Latte Language

This will be the complete language reference. I've found that a text search (with my browser) on this manual works the best, hence I have not split it up into separate sections.

If this page does not answer your question, you can read the original Latte User Manual. There is only one significant difference: No Latte does not have a macro system (yet). Otherwise, the two languages should be quite compatible.

# Latte Examples

An XHMTL document using No Latte consists of two parts: the head and the body. (The DOCTYPE and <html> tags are added automatically.)

Consider this example:

{\head {\title Hello, World!}}
{\body
{\h1 Hello, World!}

I would like to say hello to the world.
}


We can process it through nolatte-html:

% nolatte-html helloworld.latte > helloworld.html


The resulting file will have this XHTML:

<html>
<body>
<h1>Hello, World!</h1>
<p>I would like to say hello to the world.</p>
</body>
</html>


(A DOCTYPE is also added along with some "generated by" meta tags in the head, but those are unimportant details for now.)

Markup is done with curly braces { and } and with functions—\head, \title, and \body in this example. In this case, the functions used map directly to their equivalent XHTML tags.

Notice that raw text is the normal input in a No Latte program. This is in contrast to PHP and CGI Perl where you must explicitly print the XHTML from the source language. Printing the text is the default action with No Latte.

Also note that a paragraph tag was put around the one paragraph of text in the input file. The paragraph-tag inserter is smart—to the point of generating validated XHTML! Only the text in the <body> tag is given paragraph tags; the <head> is never considered for paragraph tags. Also, the <h1> was ignored because it should never contain or be contained in paragraph tags.

As seen in this simple example, there is already a savings since each close tag (e.g., </body>) turns into a single right curly brace. There's another significant savings to be had: function abstraction. Generally, you will repeat the <head> and <body> information in each page of your website; if you duplicate by hand on each page, it makes it harder to maintain and debug. No Latte allows you to create a function to abstract out the boilerplate:

{\def \my-page
{\lambda {\the-title \&content}
{\group
{\body
{\h1 \the-title}

\content
}
}}}


This function could go into a file template.latte which is included in the real pages:

{\load-file template.latte}
{\my-page {Hello, World!}
I would like to say hello to the world.
}


You can now imagine more abstraction and many more pages which can greatly simplify the overall website.

# No Latte Syntax

No Latte is an expression-based language. That is, a No Latte program consists of an expression which is evaluated, and the result of this evaluation is XHTML (hopefully).

A No Latte expression can be many different things:

• Whitespace is a sequence of spaces, tabs, and newlines.
• A word is a sequence of characters not including whitespace or the backslash: e.g., Hello, and World!.
• A quoted word is any sequence of characters (including whitespace) inside escaped double-quotes: e.g., \" Hello\" is a single word consisting of two spaces followed by Hello.
• A variable is a backslash followed by letters and digits and certain punctuation (+, -, _, ?, !): e.g., \head, \title, \the-title, \set!, \equal?.
• A group is a list of other No Latte expressions, starting with a left curly brace and ending with a right curly brace: e.g., {\h1 \the-title}, {\sort {4 9 2 3}}.

Each of these expression types are covered in more detail in this section of the language manual.

A comment in No Latte is started with \;, and extends to the end of the line.

{\h1 Hello, World!}
\;  Not seen in the output.
This is seen.


## Words

In No Latte, words are sequences of interesting characters. Whitespace, in this context, is actually considered too interesting, and it's discussed later in this language manual. Any character is considered text-worthy except for whitespace and special metacharacters (the blackslash \ and the curly braces, { and }). Special characters can be escaped to be considered part of a word. No Latte always makes the largest word it can.

Consider this example (modified from the original Latte User Manual):

In a No Latte "word", you must use \\ to escape \\, \{, and \}.


This turns into fifteen text clumps:

1. In
2. a
3. No
4. Latte
5. "word",
6. you
7. must
8. use
9. \\
10. to
11. escape
12. \\,
13. \{,
14. and
15. \}.

A quoted word is characters surrounded by escaped double-quotes like so:

\"This is a single word.\"


As indicated by the example itself, despite the spaces separating the English words, No Latte treats this as one word. This allows you to capture any whitespace you want very precisely. (See the later section on whitespace handling.) You can even specify the empty word: \"\".

The original Latte (and early versions of No Latte) required you to escape the backslash even in a quoted word. This is no longer necessary.

A quoted word also allows you to enter metacharacters without escaping them: \"\{}\" versus \\\{\}. Both result in the word \{}. Not having to escape metacharacters makes this very useful when typesetting code.

## Variables

A variable stores away one value. All variables in No Latte must be declared, and there are three ways to declare a variable.

### Defintiions

A variable can be declared at the top level with a definition:

{\def \variable-name expression}


\def is a reserved word and can be used only for a defintion; \variable-name is the name of your variable; expression is any valid No Latte expression. The expression is evaluated and that value is bound to the variable. Whenever the variable is used later in the program, the bound value is used. Variables can be defined only once; they can be used everywhere.

### Valid Variables

A variable always starts with a backslash followed by a letter or special punctuation (underscore _, hyphen -, question mark ?, and exclamation point !). You may follow those two characters with any letter, any digit, and any special punctunation.

### Let Expressions

The second way to declare a variable is with a \let expression:

{\let {{\variable1 expression1}
{\variable2 expression2}
...
{\variableN expressionN}}
body
}


The expressions are all evaluated first, and then they are bound to the variables. Then the body (which can be multiple expressions, although only the last expression's value is returned) is evaluated. The variables of a \let are lexically scoped: they are valid only in the body; they are not valid in any functions that the body calls; they are not valid after the body is finished; they shaddow any previous definitions.

### Changing a Variable

The value bound to a variable can be changed with a \set! expression.

{\set! \variable expression}


The expression is evaluated, and that value is bound to the specified variable; the old value is thrown away. It is unspecified what \set! returns; it's sole purpose is for side-effects. \set! can be used on any variable, whether defined with a \def, a \let, or a function.

### Function Parameters

The last way to declare a variable is as a function parameter. Like \let-bound variables, function-bound variables are only valid in the body of the declaring expression.

Unlike the original Latte, No Latte requires that you have at least as many arguments as positional parameters. (Latte would set "unused" positional parameters to the empty group.) Excess arguments are collected in a rest parameter (see below).

No Latte supports three kinds of parameters. The standard parameter type is the positional parameter:

{\def \foo
{\lambda \x \y \z
}
}


In this example, \x, \y, and \z are positional parameters. When \foo is invoked like so: {\foo 1 2 3}, \x is bound to 1, \y is bound to 2, and \z is bound to 3. In most programming languages, this is the only kind of parameter supported; it's the standard parameter type in mathematics.

A named parameter must be explicitly named when the function is called. For example:

{\def \foo
{\lambda \=x \=y \=z
}
}


The equals sign in the identifiers is required in the parameter list of the \lambda, but it must be dropped in the body. To invoke this function, the bindings must be more explicit, but can come in any order: {\foo \x=3 \z=5 \y=9} will ultimately compute 3+(9-5).

By default, a named parameter is bound to an empty group; any explicit assignment when the function is called overrides this default.

No Latte may or may not warn you if you have excess arguments and no rest parameter.

Finally, if there are more arguments than positional parameters, the remaining arguments are collected together in a group and assigned to a rest parameter. This is very handy for processing large amounts of text:

{\def \my-body
{\lambda \&text
{\body {\i \text}}
}
}


Again, similar to named parameters, the special character & is used only in the parameter list. Now this function can be called with any number of arguments, all of which are grouped together and bound to \text: {\my-body This is valid.} and {\my-body This longer text is also valid.}.

These three parameter types can be used in any combination. Positional parameters can be intermixed with named parameters any which way; the rest parameter (if there is one) must be last. You can have as many positional and named parameters as you like; there can be at most one rest parameter.

## Groups

Technically, a group corresponds to an array in C, C++, or Java, but it's much better and accurate to think of them as LISP- or Scheme-style lists.

The most basic and sole data structure in No Latte is the group. A group consists of zero or more subexpressions (or subvalues). Syntactically, a group is surrounded by curly braces, { and }.

The first purpose of a group is to collect values:

{Hello there}


is a group consisting of two words (plus some whitespace which we're ignoring for now). This is useful and necessary in many situations:

{\def \foo {Hello there}}
{\bar \x={Hello there}}


In the first case, the definition wouldn't even parse without curly braces; you must have exactly one expression in a definition. In the second case, \x will be bound to the whole group; without the curly braces, \x would be bound just to Hello, and there would be bound to a positional parameter.

Groups are also used for invoking functions. As seen in the last example, \bar is probably a function that has (at least) one named parameter (\x) and no positional parameters. Previous examples included function calls to \add and \subtract.

The type of group is determined at runtime: the subexpressions are evaluated, and if the first element of the group can be applied in some way (either a primitive or a function), then it is applied using the rest of the group as an argument list; otherwise, the group is returned as evaluated. So, technically, \bar in the last example could actually just evalute to some word or another group, in which case the group is returned.

## Whitespace

Normally, whitespace is not considered primary data in No Latte; the only time it is considered primary data is when it's found in a quoted word. Otherwise, whitespace is attached to the expression that follows it.

Consider this example (taken from the original Latte manual):

{\document {Our second document}
This was as exciting to
write as our first!}


No Latte sees this:

• A group with no whitespace in front of it; the group consists of the following:
• A variable reference \document with no whitespace in front of it.
• A group with a single space in front of it; the group consists of the following:
• The word Our with no whitespace in front of it.
• The word second with one space in front of it.
• The word document with one space in front of it.
• The word This with a newline and two spaces in front of it.
• The word was with a single space in front of it.
• The word as with a single space in front of it.
• ...
• The word write with a newline and two spaces in front of it.
• ...
• The word first! with a single space in front of it.

All expressions (including the groups) have whitespace attached to them. All of the preceeding whitespace (including newlines, spaces, and tabs) are attached to an expression. The expressions carry this whitespace with them, but it may not actually be used, depending on the larger context.

In general, the whitespace is discarded if the expression is evaluated in a new context. For example,

{\def \foo Hello}
.\foo.
:  \foo:


This evaluates to

.Hello.
:  Hello:


In both cases, the whitespace captured before Hello is dropped when \foo is evaluated. The only whitespace in the output comes from the last evaluated context.

\if expressions also discard attached whitespace:

{\def \bar     Hello}
{\def \baz
Hello}
${\if \foo \bar \baz}$


will always evaluate to $Hello$ (assuming \foo is defined somewhere). Not only is the whitespace from the definitions discarded, but the whitespace within the \if itself is discarded.

In Latte, the "kill whitespace" sequence could be used anywhere in whitespace; it must appear just before a real expression in No Latte.

To improve the readability of your No Latte documents, you may want to add whitespace that does not appear in the final document. The sequence \/ will kill all of the previous whitespace; this must be done at the end of the whitespace, just before an expression. Using HTML Tidy eliminates a lot of whitespace, so it is usually not necessary to worry to much about excess whitespace.

# No Latte Builtins

This section of the manual describes the basic builtins to the No Latte language. This includes the control structures, primitives, and basic functions in No Latte.

Each built-in has a level of flexibility

• Language constructs are built directly into No Latte and cannot be changed; any explicit identifiers in a pattern for a language construct are reserved words and cannot be used for anything except for the specified language construct.
• Primitives are operations that are built into No Latte itself, but their identifiers can be reassigned by you if you really want to.
• Basic functions are functions defined in the No Latte standard libraries. They're no more special than the functions that you or anyone else might define.

## Control Structures

### If Expression

{\if test then else}


Evalutes test. If the test value is true (i.e., not an empty group), the then expression is evaluated and that value is returned; otherwise (i.e., the test value was an empty group), the else expression is evaluated and that value is returned.

If else is left out, the empty group is used by default.

### Cond Expression

{\cond clause1 clause2 ... clauseN}


Like the LISP and Scheme construct, the clauses of a \cond are turned into a nested if-then-else. In pseudo-code, it is equivalent to

if first element of clause1 is true
return rest of clause1
else if first element of clause2 is true
return rest of clause2
else ...
else if first element of clauseN is true
return rest of clauseN
else
return the empty group


For example:

{\cond {{\lt? \x \y} less than!}
{{\gt? \x \y} greater than!}
{else         equals!}
}


A description of the relationship between \x and \y is returned by this expression. The word else in the last clause is always true which makes it a very readable default clause.

### While Loop

{\while test body}


As in other languages, the test is evaluated first, and if it is immediately false, it returns an empty group. Otherwise, the body is evaluated (which may consist of multiple expressions), and then the test is re-evaluated. This continues until the test fails; at that point, the accumulated evaluations of the body are returned as one group.

For example:

{\let {{\i 0}}
{\while {\lt? \i 3}
i is \i.
}
}


This evaluates to:

i is 0. i is 1. i is 2.

### Foreach Loop

{\foreach \variable group body}


The group expression is evaluated for a group; the body is then evaluated once for each element in the group, binding \variable to the current value from the group. The results from each evaluation are gathered together into one group which is returned as the result of the \foreach expression.

For example:

{\foreach \i {1 2 3}
}


evaluates to

2 3 4

More than likely, you will find the \lmap function more useful for simple operations like this one.

## Built-ins for Variables

### Basic Defintion

{\def \variable expression}


The expression is evaluated and a new variable named \variable is defined at the global level. This variable cannot be re-declared with a \def; it can be shadowed with a \let or \lambda—the global is restored when the shadowed version goes out of scope.

The expression must be exactly one expression. Anything else is an error.

### Alternative Function Definition

{\def {\variable parameters} body}


This is an alternative syntax for declaring functions; it is equivalent to this:

{\def \variable
{\lambda {parameters}
body
}}


See the section on \lambda for more information about parameters and body.

### Let Expression

{\let
{{\variable1 expression1}
{\variable2 expression2}
...
{\variableN expressionN}}
body
}


All of the expressionI are evaluated first, then each value is bound to the corresponding \variableI. (This means that the \variableI are not in effect while evaluting the binding expressions.) With these new bindings, body is evaluated, and the value of its last expression is returned. The new bindings are discarded when evaluation of the body is completed.

For the record, the \let above can be re-written as a direct application of a \lambda:

{{\lambda {\variable1 ... \variableN}
body
}
expression1 ... expressionN
}


See the section on \lambda for more information about body.

### Set Bang!

{\set! \variable expression}


Like a basic definition, the one expression is evaluated, and the value is bound to \variable; unlike a basic definition, \variable must have been defined before (by a definition, a let, or a lambda); its old binding is tossed and replaced with the new value. The new binding stays in effect as long as the scope of the affected declaration. It is an error if \variable is undeclared.

Consider this example:

{\def \x 5}
{\let {{\x 99}}
{\set! \x 123124}
\x}
\x


This evaluates to 123124 5. The \set! only affects the let-bound \x, so the global \x stays set to 5. There is no way in the body of the \let to access the \x declared in the global scope (with or without a \set!).

## Built-Ins for Functions

The basic building block for functions is the \lambda expression.

### Lambda Expression

{\lambda {parameters} body}


By itself, a lambda expression only creates what's known technically as a closure. The upshot is that a closue is something that can be evaluated later with some values that we pick later, and it works the way we expect.

Early versions of the original Latte would return the values from all of the expressions in the body; No Latte follows the semantics of the latter versions of Latte, returning the value of the last expression only.

parameters can include positional, named, and rest parameters (as described earlier). body can consist of multiple expressions, although only the value of the last expression is returned when the closure is applied.

This is a common mistake (something I still do myself!):

{\def \my-content
{\lambda {\&text}
{\h1 Welcome}

\text

Good bye!
}
}


Now {\my-content whatever} always evaluates to bye! no matter what we put in for whatever!!! This is because that one word is the last expression in the body. To get the effect we probably want, this body should be explicitly grouped:

{\def \my-content
{\lambda {\&text}
{\group
{\h1 Welcome}

\text

Good bye!
}
}
}


This is so that \set! and other side effects can be put into the body of a lambda (or let) without worrying about what they evaluate to.

### \funcall

{\funcall function arguments...}


\funcall first evaluates function and the arguments; then it applies the function-value to the evaluates arguments. An example:

{\funcall \add 2 3 4}


evaluates to 9. Frankly, it's the same leaving \funcall out (although using \funcall might be slightly slower).

### \apply

{\apply function arguments... last-argument}


\apply works the same as \funcall except that if last-argument evaluates to a group, the elements of that group are used as further arguments. Consequently, all of these evaluate to 9:

{\apply \add 2 3 4}
{\apply \add 2 3 4 {}}


Of course, any of those elements could be more interesting expressions, and the group itself might be the result of some expression.

### \compose

{\compose function1 function2}


\compose returns an expression equivalent to this:

{\lambda {\x} {function1 {function2 \x}}}


function1 and function2 must both evaluate to functions of one parameter (positional or rest, not named).

### \lmap

{\lmap function group}


function is evaluated for a function of one parameter (positional or rest, not named), and group is evaluated for a group (of course). \lmap then applies the function to each element of the group, and returns a new group with the results. (Scheme and LISP call this function map; Ruby calls it each.)

For example,

{\lmap {\lambda {\x} {\add \x 1}} {3 4 5}}


evaluates to 4 5 6.

## Group Functions

### \append

{\append arguments...}


Each of the arguments are evaluated first, then they are combined into a group. If an evaluated argument is a group, the elements of that group are added directly to the result; otherwise, the evaluated argument itself is added.

For example:

{\append a b {c d} {e {f} g} h}


evaluates to {a b c d e {f} g h}. As evident from {f}, \append does not flatten all groups, just the top ones.

### \back

{\back group}


Synonym for \rac.

### \car

{\car group}


\car evaluates the group expression, and returns the first element. (Just like the LISP/Scheme function of the same name.)

For example,

{\car {a b c}}


evaluates to a.

Synonym for \front.

### \cdr

{\cdr group}


\cdr evaluates group for a group and returns a new group with all but the first element from the original group. (Just like the LISP/Scheme function of the same name.)

For example,

{\cdr {a b c}}


evaluates to {b c}.

The new group is a true copy of the original.

### \caar, \cadr, \cdar, \cddr

{\caar group}


Composition of \car and \cdr; e.g., \cdar is {\compose \cdr \car}.

### \cons

{\cons head tail}


Returns a new group with head added to the beginning of tail. (The original tail is not changed.) Synonym for \push-front.

### \empty?

{\empty? group}


Returns true if the group is empty, false otherwise.

### \front

{\front group}


Returns the first element of the group; synonym for \car.

### \group

{\group element...}


Yields a new group consists of the specified elements.

### \lenth

{\length group}


Returns the number of elements in the group. Overloaded to also work with text strings.

### \member?

{\member? element group}


Yields true if the element is a member of the group (as determined by \equal?), false otherwise.

### \nth

{\nth group}


Yields the nth element of the group, starting with index 0. Negative indices count from the end of the group backwards. Overloaded to work with text strings.

### \push-back

{\push-back element group}


Adds the element to the end of the group, and returns that new group (without affecting the original group). Synonym for \snoc.

### \push-front

{\push-front element group}


Adds the element to the front of the group, and returns that new group (without affecting the original group). Synonym for \cons.

### \rdc

{\rdc group}


Returns the elements of the group except the last.

### \reverse

{\reverse group}


Reverses the elements of the group. Nested groups are not reversed. For example:

{\reverse {a b c}}     => {c b a}
{\reverse {a {b c} d}} => {d b c a}


### \snoc

{\snoc element group}


Adds the element to the end of the elements.

### \subseq

{\subseq group from to}


Returns a subsequence from the group, starting at index from up to (but not including) index to. The indices can be negative (and thus counted from the end of the group); to can be omitted and defaults to the length of the group (i.e., through to the last element).

Exampes:

{\subseq {a b c d e} 1 3} => {b c}
{\subseq {a b c d e} -2}  => {d e}


## Boolean Functions

The empty group {} is false; everything else is true.

### \and

{\and expressions...}


Evaluates the expressions, and returns the last value if they all evaluate to anything but the empty group. An empty group is any one of the evaluations result in one. In other words, it returns a true value if all the expressions result in true evaluations; false otherwise. Presently, this is not a short-circuiting evaluation; all of the expressions are evaluated.

### \not

{\not expression}


Evaluates the expression, and logically negates it. You are only guaranteed that {\not {}} is some true value, so if it happens to be the text true now, not plan on it for the future.

### \or

{\or expressions...}


Evaluates the expressions, and returns the first value that evaluates to true. An empty group (i.e. a false value) is returned if all evaluations are false. Presently, this is not a shirt-circuiting evaluation; all of the expressions are evaluated.

## Text Functions

Keep in mind how No Latte treats whitespace. In the case of function arguments, whitespace is merely a separator between arguments. If you want whitespace in the results, you may have to quote them with explicit quotes, e.g., \".

### \concat

{\concat text...}


Evaluates the arguments as text, and concatenates the results together. If any arguments are not text, the function results in an error. Synonym for \string-append.

### \downcase

{\downcase text...}


Evaluates the arguments as text, and returns the lower-case equivalents in a group.

### \explode

{\explode text...}


Evaluates the arguments as text, and constructs a group consisting of the characters of all of the text strings.

### \length

{\length text}


Returns the number of character in text. \length is overloaded to also work with a group, so be careful what you pass to it.

### \nth

{\nth index text}


Returns the character at the specified index (with 0-based indexing). \nth is overloaded to also handle groups.

### \string-append

{\string-append text...}


Evaluates to the concatenation of all of the text strings. Synonym for \concat.

### \string-ge?

{\string-ge? text...}


Synonym for \string-greater-equal?.

### \string-greater-equal?

{\string-greater-equal? text...}


Evaluates to true if each text string is greater than or equal to the one after it. If the comparison ever fails, false is returned. If one of the arguments is not text, an error is generated. Synonym for \string-ge?.

### \string-greater?

{\string-greater? text}


Evaluates to true if each text string is greater than the one after it. Otherwise, it evaluates to false. Synonym for \string-gt?.

### \string-gt?

{\string-gt? text}


Synonym for \string-greater?.

### \string-le?

{\string-le? text...}


Synonym for \string-less-equal?.

### \string-less-equal?

{\string-less-equal? text...}


Evaluates to true if each text string is less than or equal to the next; otherwise it evaluates to false. Synonym for \string-le?.

### \string-less?

{\string-less? text...}


Evaluates the arguments as text; evaluates (as a whole) to true if each text is less than the next; otherwise it evaluates to false. Synonym for \string-lt?.

### \substr

{\substr text from to}


Evaluates to a substring of text, starting at index from up to (but not including) index to. Indexing is 0 based; negative indexes are counted backwards from the end of the string. If to is omitted, the end of the string is used implied.

Examples:

{\substr abcde 1 3} => bc
{\substr abcde -2}  => de


### \upcase

{\upcase text...}


Evaluates to a group of text where each original text string is converted to all uppercase letters.

## Arithmetic Functions

All arithmetic in No Latte is integer based.

### \add

{\add number...}


Adds together all of the given numbers.

### \divide

{\divide number...}


Divides the numbers from left to right. Division by zero triggers an error.

### \ge?

{\ge? number...}


Synonym for \greater-equal?.

### \greater-equal?

{\greater-equal? number...}


Evaluates to true if each number is greater than or equal to the next; otherwise, evaluates to false. Synonym for \ge?.

### \greater?

{\greater? number...}


Evaluates to true if each number is greater than the next; otherwise, it evaluates to false. Synonym for gt?.

### \gt?

{\gt? number...}


Synonym for \gt?.

### \le?

{\le? number...}


Synonym for \less-equal?.

### \less-equal?

{\less-equal? number...}


Evaluates to true if each number is less than or equal to the next; false, otherwise. Synonym for \le?.

### \less?

{\less? number...}


Evaluates to true if each number is less than the next; false, otherwise. Synonym for \lt?.

### \lt?

{\lt? number...}


Synonym for \less?.

### \modulo

{\modulo a b}


Evaluates to the modulus of a and b.

### \multiply

{\multiply number...}


Returns the product of the numbers.

### \random

{\random n}


Returns a random integer greater than or equal to 0 and less than n.

### \subtract

{\subtract number...}


If a single number is given, returns the negative value of that number. Otherwise, starting with the first number, each subsequent number is subtracted from it.

### \zero?

{\zero? number}


Evaluates to true if number is 0; false, otherwise.

## File Functions

### \file-contents

{\file-contents filename}


Returns, as a text string, the contents of the specified file.

### \process-output

{\process-output program arg...}


Runs the program on the system with the specified arguments; output of the program is returned a text string. Does not work on Windows machines. Yet.

### \load-file

{\load-file filename}


Evaluates the contents of the specified file as No Latte code. Textual results are discard, but all definitions and side effects take effect.

### \load-library

{\load-library filename}


Like \load-file, evaluates the contents of the file, and only definitions and side-effects have effect.

The primary difference is that \load-library will search for the file in the "No Latte path". By default, this is /usr/local/share/latte and .; it can be set by setting the environment variable LATTE_PATH.

### \include

{\include filename}


Evaluates the content of the specified file as No Latte code. Both textual results and side effects are included in the output and further execution.

## Other Functions

### \equal?

{\equal? value...}


Returns true if all of the values are equal (deeply so); false, otherwise.

### \error

{\error text...}


Exits from the interpreter with the specified text as an error message.

### \group?

{\group? value}


Return true if the value is a group, false otherwise.

### \operator?

{\operator? value}


Return true if the value is an operator (i.e., a function), false otherwise.

### \string?

{\string? value}


Return true if the value is a text string, false otherwise.

### \warn

{\warn text...}


Emits a warning message on the standard error as specified by the text arguments.

## Predefined Variables

### \__latte-version__

Contains the version number of the No Latte interpreter.

{\__latte-version} => No Latte 0.3alpha


© 2007. Developer and website author: Jeremy D. Frens