Current section
Files
Jump to
Current section
Files
doc/man/lfe_guide.7
.\" Automatically generated by Pandoc 3.3
.\"
.TH "lfe_guide" "7" "2008\-2020" ""
.SH NAME
lfe_guide \- Lisp Flavoured Erlang User Guide
.SH SYNOPSIS
Note: {{ \&...
}} is used to denote optional syntax.
.SH LITERALS AND SPECIAL SYNTACTIC RULES
.SS Integers
Integers can be written in various forms and number bases:
.IP \[bu] 2
Regular decimal notation:
.IP
.EX
1234 \-123 0
.EE
.IP \[bu] 2
Binary notation:
.IP
.EX
#b0 #b10101 #b\-1100
.EE
.IP \[bu] 2
Binary notation (alternative form):
.IP
.EX
#*0 #*10101 #*\-1100
.EE
.IP \[bu] 2
Octal notation:
.IP
.EX
#o377 #o\-111
.EE
.IP \[bu] 2
Explicitly decimal notation:
.IP
.EX
#d1234 #d\-123 #d0
.EE
.IP \[bu] 2
Hexadecimal notation:
.IP
.EX
#xc0ffe #x\-01
.EE
.IP \[bu] 2
Notation with explicit base (up to 36):
.IP
.EX
#2r1010 #8r377 #36rhelloworld
.EE
.IP \[bu] 2
Character notation (the value is the Unicode code point of the
character):
.IP
.EX
#\[rs]a #\[rs]$ #\[rs]ä
.EE
.IP \[bu] 2
Character notation with the value in hexadecimal:
.IP
.EX
#\[rs]x1f42d;
.EE
.PP
In all these forms, the case of the indicating letter is not
significant, i.e.\ \f[CR]#b1010\f[R] and \f[CR]#B1010\f[R] are identical
as are \f[CR]#16rf00\f[R] and \f[CR]#16Rf00\f[R].
.PP
Similarly, the case is not significant for digits beyond 9 (i.e.\ `a',
`b', `c', \&...
for number bases larger than 10), e.g.\ \f[CR]#xabcd\f[R] is the same as
\f[CR]#xABCD\f[R] and can even be mixed in the same number,
e.g.\ \f[CR]#36rHelloWorld\f[R] is valid and the same number as
\f[CR]#36Rhelloworld\f[R] and \f[CR]#36rHELLOWORLD\f[R].
.PP
The character notation using hexadecimal code representation
(\f[CR]#\[rs]x....;\f[R]) is basically the same thing as the regular
hexadecimal notation \f[CR]#x...\f[R] except that it conveys to the
reader that a character is intended and that it does a sanity check on
the value (e.g.\ negative numbers and value outside the Unicode range
are not permitted).
.SS Floating point numbers
There is only one type of floating point numbers and the literals are
written in the usual way, e.g.\ these are all valid floating point
numbers:
.IP
.EX
1.0 +1.0 \-1.0 1.0e10 1.111e\-10
.EE
.PP
The one thing to watch out for is that you cannot omit the part before
or after the decimal point if it is zero.
E.g.
the following are not valid forms: \f[CR]100.\f[R] or \f[CR].125\f[R].
.SS Strings
There are two forms of strings: list strings and binary strings.
.SS List Strings
List strings are just lists of integers (where the values have to be
from a certain set of numbers that are considered valid characters) but
they have their own syntax for literals (which will also be used for
integer lists as an output representation if the list contents looks
like it is meant to be a string): \[lq]any text between double quotes
where \[dq] and other special characters like \f[CR]\[rs]n\f[R] can be
escaped\[rq].
.PP
As a special case you can also write out the character number in the
form \f[CR]\[rs]xHHH;\f[R] (where \[lq]HHH\[rq] is an integer in
hexadecimal notation),
e.g.\ \f[CR]\[dq]\[rs]x61;\[rs]x62;\[rs]x63;\[dq]\f[R] is a complicated
way of writing \f[CR]\[dq]abc\[dq]\f[R].
This can be convenient when writing Unicode letters not easily typeable
or viewable with regular fonts.
E.g.
\f[CR]\[dq]Cat: \[rs]\[rs]x1f639;\[dq]\f[R] might be easier to type (and
view on output devices without a Unicode font) then typing the actual
Unicode letter.
.SS Binary Strings
Binary strings are just like list strings but they are represented
differently in the virtual machine.
The simple syntax is \f[CR]#\[dq]...\[dq]\f[R], e.g.
\f[CR]#\[dq]This is a binary string \[rs]n with some \[rs]\[dq]escaped\[rs]\[dq] and quoted (\[rs]\[rs]x1f639;) characters\[dq]\f[R]
.PP
You can also use the general format for creating binaries
(\f[CR]#B(...)\f[R], described below), e.g.\ \f[CR]#B(\[dq]a\[dq])\f[R],
\f[CR]#\[dq]a\[dq]\f[R], and \f[CR]#B(97)\f[R] are all the same binary
string.
.SS Character Escaping
Certain control characters can be more readably included by using their
escaped name:
.IP
.EX
| Escaped name | Character |
|\-\-\-\-\-\-\-\-\-\-\-\-\-\-+\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-\-|
| \[rs]b | Backspace |
| \[rs]t | Tab |
| \[rs]n | Newline |
| \[rs]v | Vertical tab |
| \[rs]f | Form Feed |
| \[rs]r | Carriage Return |
| \[rs]e | Escape |
| \[rs]s | Space |
| \[rs]d | Delete |
.EE
.PP
Alternatively you can also use the hexadecimal character encoding,
e.g.\ \f[CR]\[dq]a\[rs]nb\[dq]\f[R] and \f[CR]\[dq]a\[rs]x0a;b\[dq]\f[R]
are the same string.
.SS Triple\-quoted Strings
LFE\[cq]s triple\-quote strings are modelled on those in Erlang so we
will use their description of them.
.PP
Strings, both list strings and binary strings, can also be written as
triple\-quoted strings, which can be indented over multiple lines to
follow the indentation of the surrounding code.
They are also verbatim, that is, they do not allow escape sequences, and
thereby do not need double quote characters to be escaped.
.PP
Example, with verbatim double quote characters:
.IP
.EX
\[dq]\[dq]\[dq]
Line \[dq]1\[dq]
Line \[dq]2\[dq]
\[dq]\[dq]\[dq]
.EE
.PP
That is equivalent to the normal single quoted string (which also allows
newlines):
.IP
.EX
\[dq]Line \[rs]\[dq]1\[rs]\[dq]
Line \[rs]\[dq]2\[rs]\[dq]\[dq]
.EE
.PP
The opening and the closing lines have the delimiters: the
\[lq]\[lq]\[rq] characters.
The lines between them are the content lines.
The newline on the opening line is not regarded as string content, nor
is the newline on the last content line.
.PP
The indentation is defined by the white space character sequence
preceding the delimiter on the closing line.
That character sequence is stripped from all content lines.
There can only be white space before the delimiter on the closing line,
or else it is regarded as a content line.
.PP
The opening line is not allowed to have any characters other than white
space after the delimiter, and all content lines must start with the
defined indentation character sequence, otherwise the string has a
syntax error.
.PP
Here is a larger example:
.IP
.EX
\[dq]\[dq]\[dq]
First line starting with two spaces
Not escaped: \[dq]\[rs]t \[rs]r \[rs]xFF\[dq] and \[dq]\[dq]\[dq]
\[dq]\[dq]\[dq]
.EE
.PP
That corresponds to the normal string:
.IP
.EX
\[dq] First line starting with two spaces
Not escaped: \[rs]\[dq]\[rs]\[rs]t \[rs]\[rs]r \[rs]\[rs]xFF\[rs]\[dq] and \[rs]\[dq]\[rs]\[dq]\[rs]\[dq]
\[dq]
.EE
.PP
Binary strings can also be written as triple\-quoted strings:
.IP
.EX
#\[dq]\[dq]\[dq]
Line \[dq]1\[dq]
Line \[dq]2\[dq]
\[dq]\[dq]\[dq]
.EE
.PP
which correspnds to the binary:
.IP
.EX
#\[dq]Line \[rs]\[dq]1\[rs]\[dq]\[rs]nLine \[rs]\[dq]2\[rs]\[dq]\[dq]
.EE
.SS Binaries
We have already seen binary strings, but the \f[CR]#B(...)\f[R] syntax
can be used to create binaries with any contents.
Unless the contents is a simple integer you need to annotate it with a
type and/or size.
.PP
Example invocations are that show the various annotations:
.IP
.EX
> #B(42 (42 (size 16)) (42 (size 32)))
#B(42 0 42 0 0 0 42)
> #B(\-42 111 (\-42 (size 16)) 111 (\-42 (size 32)))
#B(\-42 111 (\-42 (size 16)) 111 (\-42 (size 32)))
> #B((42 (size 32) big\-endian) (42 (size 32) little\-endian))
#B(0 0 0 42 42 0 0 0)
> #B((1.23 float) (1.23 (size 32) float) (1.23 (size 64) float))
#B(63 243 174 20 122 225 71 174 63 157 112 164 63 243 174 20
122 225 71 174)
> #B((#\[dq]a\[dq] binary) (#\[dq]b\[dq] binary))
#\[dq]ab\[dq]
.EE
.PP
Learn more about \[lq]segments\[rq] of binary data e.g.\ in \[lq]\c
.UR http://learnyousomeerlang.com/starting-out-for-real#bit-syntax
Learn You Some Erlang
.UE \c
\[rq] \c
.UR http://learnyousomeerlang.com/starting-out-for-real#bit-syntax
.UE \c
\&.
.SS Lists
Lists are formed either as \f[CR]( ... )\f[R] or \f[CR][ ... ]\f[R]
where the optional elements of the list are separated by some form or
whitespace.
For example:
.IP
.EX
()
(the empty list)
(foo bar baz)
(foo
bar
baz)
.EE
.SS Tuples
Tuples are written as \f[CR]#(value1 value2 ...)\f[R].
The empty tuple \f[CR]#()\f[R] is also valid.
.SS Maps
Maps are written as \f[CR]#M(key1 value1 key2 value2 ...)\f[R] The empty
map is also valid and written as \f[CR]#M()\f[R].
.SS Structs
Structs are written as
\f[CR]#S(struct\-name key1 value1 key2 value2 ...)\f[R].
.PP
Note that structs cannot be created with the literal syntax, the
\f[CR](struct mod\-name ...)\f[R] form must be used.
.SS Symbols
Things that cannot be parsed as any of the above are usually considered
as a symbol.
.PP
Simple examples are \f[CR]foo\f[R], \f[CR]Foo\f[R], \f[CR]foo\-bar\f[R],
\f[CR]:foo\f[R].
But also somewhat surprisingly \f[CR]123foo\f[R] and
\f[CR]1.23e4extra\f[R] (but note that illegal digits don\[cq]t make a
number a symbol when using the explicit number base notation,
e.g.\ \f[CR]#b10foo\f[R] gives an error).
.PP
Symbol names can contain a surprising breadth or characters, basically
all of the latin\-1 character set without control character, whitespace,
the various brackets, double quotes and semicolon.
.PP
Of these, only \f[CR]|\f[R], \f[CR]\[rs]\[aq]\f[R], \f[CR]\[aq]\f[R],
\f[CR],\f[R], and \f[CR]#\f[R] may not be the first character of the
symbol\[cq]s name (but they \f[I]are\f[R] allowed as subsequent
letters).
.PP
I.e.
these are all legal symbols: \f[CR]foo\f[R], \f[CR]foo\f[R],
\f[CR]µ#\f[R], \f[CR]±1\f[R], \f[CR]451°F\f[R].
.PP
Symbols can be explicitly constructed by wrapping their name in vertical
bars, e.g.\ \f[CR]|foo|\f[R], \f[CR]|symbol name with spaces|\f[R].
In this case the name can contain any character of in the range from 0
to 255 (or even none, i.e.\ \f[CR]||\f[R] is a valid symbol).
The vertical bar in the symbol name needs to be escaped:
\f[CR]|symbol with a vertical bar \[rs]| in its name|\f[R] (similarly
you will obviously have to escape the escape character as well).
.SS Comments
Comments come in two forms: line comments and block comments.
.PP
Line comments start with a semicolon (\f[CR];\f[R]) and finish with the
end of the line.
.PP
Block comments are written as \f[CR]#| comment text |#\f[R] where the
comment text may span multiple lines but my not contain another block
comment, i.e.\ it may not contain the character sequence \f[CR]#|\f[R].
.SS Evaluation While Reading
\f[CR]#.(... some expression ...)\f[R].
E.g.
\f[CR]#.(+ 1 1)\f[R] will evaluate the \f[CR](+ 1 1)\f[R] while it reads
the expression and then be effectively \f[CR]2\f[R].
.SH Supported forms
.SS Core forms
.IP
.EX
(quote e)
(cons head tail)
(car e)
(cdr e)
(list e ... )
(tuple e ... )
(tref tuple index)
(tset tuple index val)
(binary seg ... )
(map key val ...)
(map\-size map) (msiz m)
(map\-get map key) (mref m k)
(map\-set map key val ...) (mset m k v ...)
(map\-update map key val ...) (mupd m k v ...)
(map\-remove map key ...) (mrem m k k ...)
(lambda (arg ...) ...)
(match\-lambda
((arg ... ) {{(when e ...)}} ...) \- Matches clauses
... )
(function func\-name arity) \- Function reference
(function mod\-name func\-name arity)
(let ((pat {{(when e ...)}} e)
...)
... )
(let\-function ((name lambda|match\-lambda) \- Local functions
... )
... )
(letrec\-function ((name lambda|match\-lambda) \- Local functions
... )
... )
(let\-macro ((name lambda\-match\-lambda) \- Local macros
...)
...)
(progn ... )
(if test true\-expr {{false\-expr}})
(case e
(pat {{(when e ...)}} ...)
... ))
(receive
(pat {{(when e ...)}} ... )
...
(after timeout ... ))
(catch ... )
(try
e
{{(case ((pat {{(when e ...)}} ... )
... ))}}
{{(catch
((tuple type value stacktrace)|_ {{(when e ...)}}
\- Must be tuple of length 3 or just _!
... )
... )}}
{{(after ... )}})
(funcall func arg ... )
(call mod func arg ... ) \- Call to Mod:Func(Arg, ... )
(define\-record name fields)
(record name field val ...)
(is\-record record name)
(record\-index name field)
(record\-field record name field)
(record\-update record name field val ...)
(define\-struct fields)
(struct mod\-name field val ...)
(is\-struct struct)
(is\-struct struct name)
(struct\-field struct name field)
(struct\-update struct name field val ...)
(define\-module name meta\-data attributes)
(extend\-module meta\-data attributes)
(define\-function name meta\-data lambda|match\-lambda)
(define\-macro name meta\-data lambda|match\-lambda)
(define\-type type definition)
(define\-opaque\-type type definition)
(define\-function\-spec func spec)
.EE
.SS Basic macro forms
.IP
.EX
(: mod func arg ... ) =>
(call \[aq]mod \[aq]func arg ... )
(mod:func arg ... ) =>
(call \[aq]mod \[aq]func arg ... )
(? {{timeout {{default}} }})
(++ ... )
(\-\- ... )
(list* ... )
(let* (... ) ... )
(flet ((name (arg ...) {{doc\-string}} ...)
...)
...)
(flet* (...) ... )
(fletrec ((name (arg ...) {{doc\-string}} ...)
...)
...)
(cond (test body ...)
...
((?= pat expr) ...)
...
(else ...))
(andalso ... )
(orelse ... )
(fun func arity)
(fun mod func arity)
(lc (qual ...) expr)
(list\-comp (qual ...) expr)
(bc (qual ...) bitstringexpr)
(binary\-comp (qual ...) bitstringexpr)
(ets\-ms ...)
(trace\-ms ...)
.EE
.SS Common Lisp inspired macros
.IP
.EX
(defun name (arg ...) {{doc\-string}} ...)
(defun name
{{doc\-string}}
((argpat ...) ...)
...)
(defmacro name (arg ...) {{doc\-string}} ...)
(defmacro name arg {{doc\-string}} ...)
(defmacro name
{{doc\-string}}
((argpat ...) ...)
...)
(defsyntax name
(pat exp)
...)
(macrolet ((name (arg ...) {{doc\-string}} ...)
...)
...)
(syntaxlet ((name (pat exp) ...)
...)
...)
(prog1 ...)
(prog2 ...)
(defmodule name ...)
(defrecord name ...)
(defstruct ...)
.EE
.SH Patterns
Written as normal data expressions where symbols are variables and use
quote to match explicit values.
Binaries and tuples have special syntax.
.IP
.EX
{ok,X} \-> (tuple \[aq]ok x)
error \-> \[aq]error
{yes,[X|Xs]} \-> (tuple \[aq]yes (cons x xs))
<<34,U:16,F/float>> \-> (binary 34 (u (size 16)) (f float))
[P|Ps]=All \-> (= (cons p ps) all)
.EE
.PP
Repeated variables are supported in patterns and there is an automatic
comparison of values.
.PP
\f[CR]_\f[R] as the \[lq]don\[cq]t care\[rq] variable is supported.
This means that the symbol \f[CR]_\f[R], which is a perfectly valid
symbol, can never be bound through pattern matching.
.PP
Aliases are defined with the \f[CR](= pattern1 pattern2)\f[R] pattern.
As in Erlang patterns they can be used anywhere in a pattern.
.PP
\f[I]CAVEAT\f[R] The lint pass of the compiler checks for aliases and if
they are possible to match.
If not an error is flagged.
This is not the best way.
Instead there should be a warning and the offending clause removed, but
later passes of the compiler can\[cq]t handle this yet.
.SH Guards
Wherever a pattern occurs (in let, case, receive, lc, etc.)
it can be followed by an optional guard which has the form
\f[CR](when test ...)\f[R].
Guard tests are the same as in vanilla Erlang and can contain the
following guard expressions:
.IP
.EX
(quote e)
(cons gexpr gexpr)
(car gexpr)
(cdr gexpr)
(list gexpr ...)
(tuple gexpr ...)
(tref gexpr gexpr)
(binary ...)
(record ...) \- Also the macro versions
(is\-record ...)
(record\-field ...)
(record\-index ...)
(map ...)
(msiz ...) (map\-size ...)
(mref ...) (map\-get ...)
(mset ...) (map\-set ...)
(mupd ...) (map\-update ...)
(type\-test e) \- Type tests
(guard\-bif ...) \- Guard BIFs, arithmetic,
boolean and comparison operators
.EE
.PP
An empty guard, \f[CR](when)\f[R], always succeeds as there is no test
which fails.
This simplifies writing macros which handle guards.
.SH Comments in Function Definitions
Inside functions defined with defun LFE permits optional comment strings
in the Common Lisp style after the argument list.
So we can have:
.IP
.EX
(defun max (x y)
\[dq]The max function.\[dq]
(if (>= x y) x y))
.EE
.PP
Optional comments are also allowed in match style functions after the
function name and before the clauses:
.IP
.EX
(defun max
\[dq]The max function.\[dq]
((x y) (when (>= x y)) x)
((x y) y))
.EE
.PP
This is also possible in a similar style in local functions defined by
flet and fletrec:
.IP
.EX
(defun foo (x y)
\[dq]The max function.\[dq]
(flet ((m (a b)
\[dq]Local comment.\[dq]
(if (>= a b) a b)))
(m x y)))
.EE
.SH Variable Binding and Scoping
Variables are lexically scoped and bound by \f[CR]lambda\f[R],
\f[CR]match\-lambda\f[R] and \f[CR]let\f[R] forms.
All variables which are bound within these forms shadow variables bound
outside but other variables occurring in the bodies of these forms will
be imported from the surrounding environments.No variables are exported
out of the form.
So for example the following function:
.IP
.EX
(defun foo (x y z)
(let ((x (zip y)))
(zap x z))
(zop x y))
.EE
.PP
The variable \f[CR]y\f[R] in the call \f[CR](zip y)\f[R] comes from the
function arguments.
However, the \f[CR]x\f[R] bound in the \f[CR]let\f[R] will shadow the
\f[CR]x\f[R] from the arguments so in the call \f[CR](zap x z)\f[R] the
\f[CR]x\f[R] is bound in the \f[CR]let\f[R] while the \f[CR]z\f[R] comes
from the function arguments.
In the final \f[CR](zop x y)\f[R] both \f[CR]x\f[R] and \f[CR]y\f[R]
come from the function arguments as the \f[CR]let\f[R] does not export
\f[CR]x\f[R].
.SH Function Binding and Scoping
Functions are lexically scoped and bound by the top\-level
\f[CR]defun\f[R] and by the macros \f[CR]flet\f[R] and
\f[CR]fletrec\f[R].
LFE is a Lisp\-2 so functions and variables have separate namespaces and
when searching for function both name and arity are used.
This means that when calling a function which has been bound to a
variable using \f[CR](funcall func\-var arg ...)\f[R] is required to
call \f[CR]lambda\f[R]/\f[CR]match\-lambda\f[R] bound to a variable or
used as a value.
.PP
Unqualified functions shadow as stated above which results in the
following order within a module, outermost to innermost:
.IP \[bu] 2
Predefined Erlang BIFs
.IP \[bu] 2
Predefined LFE BIFs
.IP \[bu] 2
Imports
.IP \[bu] 2
Top\-level defines
.IP \[bu] 2
Flet/fletrec
.IP \[bu] 2
Core forms, these can never be shadowed
.PP
This means that it is perfectly legal to shadow BIFs by imports,
BIFs/imports by top\-level functions and BIFs/imports/top\-level by
\f[CR]fletrec\f[R]s.
In this respect there is nothing special about BIFs, they just behave as
predefined imported functions, a whopping big
\f[CR](import (from erlang ...))\f[R].
EXCEPT that we know about guard BIFs and expression BIFs.
If you want a private version of \f[CR]spawn\f[R] then define it, there
will be no warnings.
.PP
\f[I]CAVEAT\f[R] This does not hold for the supported core forms.
These can be shadowed by imports or redefined but the compiler will
\f[I]always\f[R] use the core meaning and never an alternative.
Silently!
.SH Module definition
The basic forms for defining a module and extending its metadata and
attributes are:
.IP
.EX
(define\-module name meta\-data attributes)
(extend\-module meta\-data attributes)
.EE
.PP
The valid meta data is \f[CR](type typedef ...)\f[R],
\f[CR](opaque typedef ...)\f[R], \f[CR](spec function\-spec ...)\f[R]
and \f[CR](record record\-def ...)\f[R].
Each can take multiple definitions in one meta form.
.PP
Attributes declarations have the syntax
\f[CR](attribute value\-1 ...)\f[R] where the attribute value is a list
off the values in the declaration
.PP
To simplify defining modules there is a predefined macro:
.IP
.EX
(defmodule name
\[dq]This is the module documentation.\[dq]
(export (f 2) (g 1) ... )
(export all) ;Export all functions
(import (from mod (f1 2) (f2 1) ... )
(rename mod ((g1 2) m\-g1) ((g2 1) m\-g2) ... ))
(module\-alias (really\-long\-module\-name rlmn) ...)
(attr\-1 value\-1 value\-2)
{meta meta\-data ...)
... )
.EE
.PP
We can have multiple export and import attributes within module
declaration.
The \f[CR](export all)\f[R] attribute is allowed together with other
export attributes and overrides them.
Other attributes which are not recognized by the compiler are allowed
and are simply passed on to the module and can be accessed with the
\f[CR]module_info/0\-1\f[R] functions.
.PP
In the \f[CR]import\f[R] attribute the \f[CR](from mod (f1 2) ...)\f[R]
means that the call \f[CR](f1 \[aq]everything 42)\f[R] will be converted
by the compiler to \f[CR](mod:f1 \[aq]everything 42))\f[R] while the
\f[CR](rename mod ((g2 2) m\-g1) ...)\f[R] means that the call
\f[CR](m\-g1 \[aq]everything 42)\f[R] will be converted to
\f[CR](mod:g1 \[aq]everything 42)\f[R].
The \f[CR]rename\f[R] form can be used as compact way of indicating the
imported function\[cq]s module.
Note that when importing a module
.IP \[bu] 2
the compiler does no checking on that module at all
.IP \[bu] 2
in the \f[CR]rename\f[R] above the functions \f[CR]g1/2\f[R] and
\f[CR]g2/1\f[R] aren\[cq]t automatically imported, only the
\[lq]renamed\[rq] functions.
.IP \[bu] 2
we do not really see in the code that we are calling a function in
another module
.PP
In the \f[CR]module\-alias\f[R] attribute the
\f[CR](really\-long\-module\-name rlmn)\f[R] declaration means that the
call \f[CR](lrmn:foo \[aq]everything 42)\f[R] will be converted by the
compiler to
\f[CR](really\-long\-module\-name:foo \[aq]everything 42)\f[R].
This is often used to write short module names in the code when calling
functions in modules with long names.
It is in many ways better than using \f[CR]import\f[R] as it does not
hide that we are calling a function in another module.
.SH Macros
Macro calls are expanded in both body and patterns.
This can be very useful to have both make and match macros, but be
careful with names.
.PP
A macro is function of two arguments which is a called with a list of
the arguments to the macro call and the current macro environment.
It can be either a lambda or a match\-lambda.
The basic forms for defining macros are:
.IP
.EX
(define\-macro name meta\-data lambda|match\-lambda)
(let\-macro ((name lambda|match\-lambda)
...)
.EE
.PP
Macros are definitely NOT hygienic in any form.
However, variable scoping and variable immutability remove most of the
things that can cause unhygienic macros.
It can be done but you are not going to do it by mistake.
The only real issue is if you happen to be using a variable which has
the same name as one which the macro generates, that can cause problems.
The work around for this is to give variables created in the macro
expansion really weird names like \f[CR]| \- foo \- |\f[R] which no one
in their right mind would use.
.PP
To simplify writing macros there are a number of predefined macros:
.IP
.EX
(defmacro name (arg ...) ...)
(defmacro name arg ...)
(defmacro name ((argpat ...) body) ...)
.EE
.PP
Defmacro can be used for defining simple macros or sequences of matches
depending on whether the arguments are a simple list of symbols or can
be interpreted as a list of pattern/body pairs.
In the second case when the argument is just a symbol it will be bound
to the whole argument list.
For example:
.IP
.EX
(defmacro double (a) \[ga](+ ,a ,a))
(defmacro my\-list args \[ga](list ,\[at]args))
(defmacro andalso
((list e) \[ga],e)
((cons e es) \[ga](if ,e (andalso ,\[at]es) \[aq]false))
(() \[ga]\[aq]true))
.EE
.PP
The macro definitions in a macrolet obey the same rules as defmacro.
.PP
The macro functions created by defmacro and macrolet automatically add
the second argument with the current macro environment with the name
\f[CR]$ENV\f[R].
This allows explicit expansion of macros inside the macro and also
manipulation of the macro environment.
No changes to the environment are exported outside the macro.
.PP
User defined macros shadow the predefined macros so it is possible to
redefine the built\-in macro definitions.
However, see the caveat below!
.PP
Yes, we have the backquote.
It is implemented as a macro so it is expanded at macro expansion time.
.PP
Local functions that are only available at compile time and can be
called by macros are defined using eval\-when\-compile:
.IP
.EX
(defmacro foo (x)
...
(foo\-helper m n)
...)
(eval\-when\-compile
(defun foo\-helper (a b)
...)
)
.EE
.PP
There can be many eval\-when\-compile forms.
Functions defined within an \f[CR]eval\-when\-compile\f[R] are mutually
recursive but they can only call other local functions defined in an
earlier \f[CR]eval\-when\-compile\f[R] and macros defined earlier in the
file.
Functions defined in \f[CR]eval\-when\-compile\f[R] which are called by
macros can defined after the macro but must be defined before the macro
is used.
.PP
Scheme\[cq]s syntax rules are an easy way to define macros where the
body is just a simple expansion.
The are implemented the the module \f[CR]scm\f[R] and are supported with
\f[CR]scm:define\-syntax\f[R] and \f[CR]scm:let\-syntax\f[R] and the
equivalent \f[CR]scm:defsyntax\f[R] and \f[CR]scm:syntaxlet\f[R].
Note that the patterns are only the arguments to the macro call and do
not contain the macro name.
So using them we would get:
.IP
.EX
(scm:defsyntax andalso
(() \[aq]true)
((e) e)
((e . es) (case e (\[aq]true (andalso . es)) (\[aq]false \[aq]false))))
.EE
.PP
There is an include file \[lq]include/scm.lfe\[rq] which defines macros
so the names don\[cq]t have to be prefixed with \f[CR]scm:\f[R].
.PP
\f[I]CAVEAT\f[R] While it is perfectly legal to define a Core form as a
macro these will silently be ignored by the compiler.
.SH Comments in Macro Definitions
Inside macros defined with defmacro LFE permits optional comment strings
in the Common Lisp style after the argument list.
So we can have:
.IP
.EX
(defmacro double (a)
\[dq]Double macro.\[dq]
\[ga](+ ,a ,a))
.EE
.PP
Optional comments are also allowed in match style macros after the macro
name and before the clauses:
.IP
.EX
(defmacro my\-list args
\[dq]List of arguments.\[dq]
\[ga](list ,\[at]args))
(defmacro andalso
\[dq]The andalso form.\[dq]
((list e) \[ga],e)
((cons e es) \[ga](if ,e (andalso ,\[at]es) \[aq]false))
(() \[ga]\[aq]true))
.EE
.PP
This is also possible in a similar style in local functions defined by
macrolet:
.IP
.EX
(defun foo (x y)
\[dq]The max function.\[dq]
(macrolet ((m (a b)
\[dq]Poor macro definition.\[dq]
\[ga](if (>= ,a ,b) ,a ,b)))
(m x y)))
.EE
.SH Extended cond
The tests in \f[CR]cond\f[R] are Erlang tests in that they should return
either \f[CR]true\f[R] or \f[CR]false\f[R].
If no test succeeds then the \f[CR]cond\f[R] does not generate an
exception but just returns \f[CR]false\f[R].
There is a simple catch\-all \[lq]test\[rq] \f[CR]else\f[R] which must
last and can be used to handle when all tests fail.
.PP
Cond has been extended with the extra test \f[CR](?= pat expr)\f[R]
which tests if the result of \f[CR]expr\f[R] matches the pattern
\f[CR]pat\f[R].
If so it binds the variables in \f[CR]pa\f[R]t which can be used in the
\f[CR]cond\f[R].
A optional guard is allowed here.
An example:
.IP
.EX
(cond ((foo x) ...)
((?= (cons x xs) (when (is_atom x)) (bar y))
(fubar xs (baz x)))
((?= (tuple \[aq]ok x) (baz y))
(zipit x))
...
(else \[aq]yay))
.EE
.SH Records
Records are tuples with the record name as first element and the rest of
the fields in order exactly like \[lq]normal\[rq] Erlang records.
As with Erlang records the default default value is the atom
`undefined'.
.PP
The basic forms for defining a record, creating, accessing and updating
it are:
.IP
.EX
(define\-record name (field | (field) |
(field default\-value) |
(field default\-value type) ...))
(record name field value field value ...)
(is\-record record name)
(record\-index name field)
(record\-field record name field)
(record\-update record name field value field value ...)
.EE
.PP
Note that the list of field/value pairs when making or updating a record
is a flat list.
.PP
Note that the old \f[CR]make\-record\f[R] form has been deprecated and
is replaced by \f[CR]record\f[R] which better matches other constructors
like \f[CR]tuple\f[R] and \f[CR]map\f[R].
It still exists but should not be used.
.PP
We will explain these forms with a simple example.
To define a record we do:
.IP
.EX
(define\-record person
((name \[dq]\[dq])
(address \[dq]\[dq] (string))
(age)))
.EE
.PP
which defines a record \f[CR]person\f[R] with the fields \f[CR]name\f[R]
(default value \f[CR]\[dq]\[dq]\f[R]), \f[CR]address\f[R] (default value
\f[CR]\[dq]\[dq]\f[R] and type \f[CR](string)\f[R]) and \f[CR]age\f[R].
To make an instance of a \f[CR]person\f[R] record we do:
.IP
.EX
(record person name \[dq]Robert\[dq] age 54)
.EE
.PP
The \f[CR]record\f[R] form is also used to define a pattern.
.PP
We can get the value of the \f[CR]address\f[R] field in a person record
and set it by doing (the variable \f[CR]robert\f[R] references a
\f[CR]person\f[R] record):
.IP
.EX
(record\-field robert person address)
(record\-update robert person address \[dq]my home\[dq] age 55)
.EE
.PP
Note that we must include the name of the record when accessing it and
there is no need to quote the record and field names as these are always
literal atoms.
.PP
To simplify defining and using records there is a predefined macro:
.IP
.EX
(defrecord name
(field) | field
(field default\-value)
(field default\-value type)
... )
.EE
.PP
This will create access macros for record creation and accessing and
updating fields.
The \f[CR]make\-\f[R], \f[CR]match\-\f[R] and \f[CR]update\-\f[R] forms
takes optional argument pairs field\-name value to get non\-default
values.
E.g.
for
.IP
.EX
(defrecord person
(name \[dq]\[dq])
(address \[dq]\[dq] (string))
(age))
.EE
.PP
the following will be generated:
.IP
.EX
(make\-person {{field value}} ... )
(match\-person {{field value}} ... )
(is\-person r)
(fields\-person)
(update\-person r {{field value}} ... )
(person\-name r)
(person\-name)
(update\-person\-name r name)
(person\-age r)
(person\-age)
(update\-person\-age r age)
(person\-address r)
(person\-address)
(update\-person\-address r address)
.EE
.IP \[bu] 2
\f[CR](make\-person name \[dq]Robert\[dq] age 54)\f[R] \- Will create a
new person record with the name field set to \[lq]Robert\[rq], the age
field set to 54 and the address field set to the default \[lq]\[lq].
.IP \[bu] 2
\f[CR](match\-person name name age 55)\f[R] \- Will match a person with
age 55 and bind the variable name to the name field of the record.
Can use any variable name here.
.IP \[bu] 2
\f[CR](is\-person john)\f[R] \- Test if john is a person record.
.IP \[bu] 2
\f[CR](person\-address john)\f[R] \- Return the address field of the
person record john.
.IP \[bu] 2
\f[CR](person\-address)\f[R] \- Return the index of the address field of
a person record.
.IP \[bu] 2
\f[CR](update\-person\-address john \[dq]back street\[dq])\f[R] \-
Updates the address field of the person record john to \[lq]back
street\[rq].
.IP \[bu] 2
\f[CR](update\-person john age 35 address \[dq]front street\[dq])\f[R]
\- In the person record john update the age field to 35 and the address
field to \[lq]front street\[rq].
.IP \[bu] 2
\f[CR](fields\-person)\f[R] \- Returns a list of fields for the record.
This is useful for when using LFE with Mnesia, as the record field names
don\[cq]t have to be provided manually in the create_table call.
.IP \[bu] 2
\f[CR](size\-person)\f[R] \- Returns the size of the record tuple.
.PP
Note that the older now deprecated \f[CR]set\-\f[R] forms are still
generated.
.SH Structs
Structs in LFE are the same as Elixir structs and have been defined in
the same way so to be truly compatible.
This means that you can use structs defined in Elixr from LFE and
structs defined in LFE from Elixir.
.IP
.EX
(define\-struct (field | (field) |
(field default\-value) |
(field default\-value type) ...))
(struct name field value field value ...)
(is\-struct struct)
(is\-struct struct name)
(struct\-field struct name field)
(struct\-update struct name field value field value ...)
.EE
.PP
We will explain these forms with a simple example.
To define a struct we do:
.IP
.EX
(define\-struct ((name \[dq]\[dq])
(address \[dq]\[dq] (string))
(age)))
.EE
.PP
which defines a struct with the name of the current module with the
fields \f[CR]name\f[R] (default value \f[CR]\[dq]\[dq]\f[R]),
\f[CR]address\f[R] (default value \f[CR]\[dq]\[dq]\f[R] and type
\f[CR](string)\f[R]) and \f[CR]age\f[R].
To make an instance of struct we do:
.IP
.EX
(struct mod\-name name \[dq]Robert\[dq] age 54)
.EE
.PP
The \f[CR]struct\f[R] form is also used to define a pattern.
.PP
We can get the value of the \f[CR]address\f[R] field in the struct and
set it by doing (the variable \f[CR]robert\f[R] references a struct):
.IP
.EX
(struct\-field robert mod\-name address)
(struct\-update robert mod\-name address \[dq]my home\[dq] age 55)
.EE
.PP
Note that a struct automatically gets the name of the module in which it
is defined so that there can only be one struct defined in a module.
This mirrors how structs are implemented in Elixir.
.PP
Note that we must include the name of the struct when accessing it and
there is no need to quote the struct and field names as these are always
literal atoms.
.SH Binaries/bitstrings
A binary is
.IP
.EX
(binary seg ... )
.EE
.PP
where \f[CR]seg\f[R] is
.IP
.EX
byte
string
(val integer | float | binary | bitstring | bytes | bits |
utf8 | utf\-8 | utf16 | utf\-16 | utf32 | utf\-32
(size n) (unit n)
big\-endian | little\-endian | native\-endian
big | little | native
signed | unsigned)
.EE
.PP
\f[CR]val\f[R] can also be a string in which case the specifiers will be
applied to every character in the string.
As strings are just lists of integers these are also valid here.
In a binary constant all literal forms are allowed on input but they
will always be written as bytes.
.SH Maps
A map is created with:
.IP
.EX
(map key value ... )
.EE
.PP
To access maps there are the following forms:
.IP \[bu] 2
\f[CR](map\-size map)\f[R] \- Return the size of a map.
.IP \[bu] 2
\f[CR](map\-get map key)\f[R] \- Return the value associated with the
key in the map.
.IP \[bu] 2
\f[CR](map\-set map key val ... )\f[R] \- Set the keys in the map to
values.
This form can be used to update the values of existing keys and to add
new keys.
.IP \[bu] 2
\f[CR](map\-update map key val ... )\f[R] \- Update the keys in the map
to values.
Note that this form requires all the keys to already exist in the map.
.IP \[bu] 2
\f[CR](map\-remove map key ... )\f[R] \- Remove the keys in the map.
.PP
There are also alternate short forms \f[CR]msiz\f[R], \f[CR]mref\f[R],
\f[CR]mset\f[R], \f[CR]mupd\f[R] and \f[CR]mrem\f[R] based on the
Maclisp array reference forms.
They take the same arguments as their longer alternatives.
.SH List/binary comprehensions
List/binary comprehensions are supported as macros.
The syntax for list comprehensions is:
.IP
.EX
(lc (qual ...) expr)
(list\-comp (qual ...) expr)
.EE
.PP
where the last expr is used to generate the elements of the list.
.PP
The syntax for binary comprehensions is:
.IP
.EX
(bc (qual ...) bitstringexpr )
(binary\-comp (qual ...) bitstringexpr)
.EE
.PP
where the final expr is a bitstring expression and is used to generate
the elements of the binary.
.PP
The supported qualifiers, in both list/binary comprehensions are:
.IP
.EX
(<\- pat {{guard}} list\-expr) \- Extract elements from list
(<= bin\-pat {{guard}} binary\-expr) \- Extract elements from binary
expr \- Normal boolean test
.EE
.PP
Some examples:
.IP
.EX
(lc ((<\- v (when (> v 5)) l1)
(== (rem v 2) 0))
v)
.EE
.PP
returns a list of all the even elements of the list \f[CR]l1\f[R] which
are greater than 5.
.IP
.EX
(bc ((<= (binary (f float (size 32))) b1)
(> f 10.0))
(progn
(: io fwrite \[dq]\[ti]p\[rs]n\[dq] (list f))
(binary (f float (size 64)))))
.EE
.PP
returns a binary of floats of size 64 bits which are from the binary b1
where they are of size 32 bits and larger than 10.0.
The returned numbers are first printed.
.PP
This could also be written using a guard for the test:
.IP
.EX
(bc ((<= (binary (f float (size 32))) (when (> f 10.0)) b1))
(progn
(: io fwrite \[dq]\[ti]p\[rs]n\[dq] (list f))
(binary (f float (size 64)))))
.EE
.SH ETS and Mnesia
LFE also supports match specifications and Query List Comprehensions.
The syntax for a match specification is the same as for match\-lambdas:
.IP
.EX
(ets\-ms
((arg ... ) {{(when e ...)}} ...) \- Matches clauses
... )
.EE
.PP
For example:
.IP
.EX
(ets:select db (ets\-ms
([(tuple _ a b)] (when (> a 3)) (tuple \[aq]ok b))))
.EE
.PP
It is a macro which creates the match specification structure which is
used in \f[CR]ets:select\f[R] and \f[CR]mnesia:select\f[R].
For tracing instead of the \f[CR]ets\-ms\f[R] macro there is the
\f[CR]trace\-ms\f[R] macro which is also used in conjunction with the
\f[CR]dbg\f[R] module.
The same restrictions as to what can be done apply as for vanilla match
specifications:
.IP \[bu] 2
There is only a limited number of BIFs which are allowed
.IP \[bu] 2
There are some special functions only for use with dbg
.IP \[bu] 2
For ets/mnesia it takes a single parameter which must a tuple or a
variable
.IP \[bu] 2
For dbg it takes a single parameter which must a list or a variable
.PP
N.B.
the current macro neither knows nor cares whether it is being used in
ets/mnesia or in dbg.
It is up to the user to get this right.
.PP
Macros, especially record macros, can freely be used inside match specs.
.PP
\f[I]CAVEAT\f[R] Some things which are known not to work in the current
version are andalso, orelse and record updates.
.SH Query List Comprehensions
LFE supports QLCs for mnesia through the qlc macro.
It has the same structure as a list comprehension and generates a Query
Handle in the same way as with \f[CR]qlc:q([...])\f[R].
The handle can be used together with all the combination functions in
the module qlc.
.PP
For example:
.IP
.EX
(qlc (lc ((<\- (tuple k v) (: ets table e2)) (== k i)) v)
{{Option}})
.EE
.PP
Macros, especially record macros, can freely be used inside query list
comprehensions.
.PP
\f[I]CAVEAT\f[R] Some things which are known not to work in the current
version are nested QLCs and let/case/recieve which shadow variables.
.SH Predefined LFE functions
The following more or less standard lisp functions are predefined:
.IP
.EX
(<arith_op> expr ...)
(<comp_op> expr ...)
.EE
.PP
The standard arithmetic operators, + \- * /, and comparison operators, >
>= < =< == /= =:= =/= , can take multiple arguments the same as their
standard lisp counterparts.
This is still experimental and implemented using macros.
They do, however, behave like normal functions and evaluate ALL their
arguments before doing the arithmetic/comparisons operations.
.IP
.EX
(acons key value list)
(pairlis keys values {{list}})
(assoc key list)
(assoc\-if test list)
(assoc\-if\-not test list)
(rassoc value list)
(rassoc\-if test list)
(rassoc\-if\-not test list)
.EE
.PP
The standard association list functions.
.IP
.EX
(subst new old tree)
(subst\-if new test tree)
(subst\-if\-not new test tree)
(sublis alist tree)
.EE
.PP
The standard substitution functions.
.IP
.EX
(macroexpand\-1 expr {{environment}})
.EE
.PP
If Expr is a macro call, does one round of expansion, otherwise returns
Expr.
.IP
.EX
(macroexpand expr {{environment}})
.EE
.PP
Returns the expansion returned by calling macroexpand\-1 repeatedly,
starting with Expr, until the result is no longer a macro call.
.IP
.EX
(macroexpand\-all expr {{environment}})
.EE
.PP
Returns the expansion from the expression where all macro calls have
been expanded with macroexpand.
.PP
NOTE that when no explicit environment is given the macroexpand
functions then only the default built\-in macros will be expanded.
Inside macros and in the shell the variable $ENV is bound to the current
macro environment.
.IP
.EX
(eval expr {{environment}})
.EE
.PP
Evaluate the expression expr.
Note that only the pre\-defined lisp functions, erlang BIFs and exported
functions can be called.
Also no local variables can be accessed.
To access local variables the expr to be evaluated can be wrapped in a
let defining these.
.PP
For example if the data we wish to evaluate is in the variable expr and
it assumes there is a local variable \[lq]foo\[rq] which it needs to
access then we could evaluate it by calling:
.IP
.EX
(eval \[ga](let ((foo ,foo)) ,expr))
.EE
.SS Supplemental Common Lisp Functions
LFE provides the module cl which contains the following functions which
closely mirror functions defined in the Common Lisp Hyperspec.
Note that the following functions use zero\-based indices, like Common
Lisp (unlike Erlang, which start at index `1').
A major difference between the LFE versions and the Common Lisp versions
of these functions is that the boolean values are the LFE
\f[CR]\[aq]true\f[R] and \f[CR]\[aq]false\f[R].
Otherwise the definitions closely follow the CL definitions and
won\[cq]t be documented here.
.IP
.EX
cl:make\-lfe\-bool cl\-value
cl:make\-cl\-bool lfe\-bool
cl:mapcar function list
cl:maplist function list
cl:mapc function list
cl:mapl function list
cl:symbol\-plist symbol
cl:symbol\-name symbol
cl:get symbol pname
cl:get symbol pname default
cl:getl symbol pname\-list
cl:putprop symbol value pname
cl:remprop symbol pname
cl:getf plist pname
cl:getf plist pname default
cl:putf plist value pname ; This does not exist in CL
cl:remf plist pname
cl:get\-properties plist pname\-list
cl:elt index sequence
cl:length sequence
cl:reverse sequence
cl:some predicate sequence
cl:every predicate sequence
cl:notany predicate sequence
cl:notevery predicate sequence
cl:reduce function sequence
cl:reduce function sequence \[aq]initial\-value x
cl:reduce function sequence \[aq]from\-end \[aq]true
cl:reduce function sequence \[aq]initial\-value x \[aq]from\-end \[aq]true
cl:remove item sequence
cl:remove\-if predicate sequence
cl:remove\-if\-not predicate sequence
cl:remove\-duplicates sequence
cl:find item sequence
cl:find\-if predicate sequence
cl:find\-if\-not predicate sequence
cl:find\-duplicates sequence
cl:position item sequence
cl:position\-if predicate sequence
cl:position\-if\-not predicate sequence
cl:position\-duplicates sequence
cl:count item sequence
cl:count\-if predicate sequence
cl:count\-if\-not predicate sequence
cl:count\-duplicates sequence
cl:car list
cl:first list
cl:cdr list
cl:rest list
cl:nth index list
cl:nthcdr index list
cl:last list
cl:butlast list
cl:subst new old tree
cl:subst\-if new test tree
cl:subst\-if\-not new test tree
cl:sublis alist tree
cl:member item list
cl:member\-if predicate list
cl:member\-if\-not predicate list
cl:adjoin item list
cl:union list list
cl:intersection list list
cl:set\-difference list list
cl:set\-exclusive\-or list list
cl:subsetp list list
cl:acons key data alist
cl:pairlis list list
cl:pairlis list list alist
cl:assoc key alist
cl:assoc\-if predicate alost
cl:assoc\-if\-not predicate alost
cl:rassoc key alist
cl:rassoc\-if predicate alost
cl:rassoc\-if\-not predicate alost
cl:type\-of object
cl:coerce object type
.EE
.PP
Furthermore, there is an include file which developers may which to
utilize in their LFE programs:
\f[CR](include\-lib \[dq]lfe/include/cl.lfe\[dq])\f[R].
Currently this offers Common Lisp predicates, but may include other
useful macros and functions in the future.
The provided predicate macros wrap the various \f[CR]is_*\f[R] Erlang
functions; since these are expanded at compile time, they are usable in
guards.
The include the following:
.IP
.EX
(alivep x)
(atomp x)
(binaryp x)
(bitstringp x)
(boolp x) and (booleanp x)
(builtinp x)
(consp x)
(floatp x)
(funcp x) and (functionp x)
(intp x) and (integerp x)
(listp x)
(mapp x)
(numberp x)
(pidp x)
(process\-alive\-p x)
(recordp x tag)
(recordp x tag size)
(refp x) and (referencep x)
(tuplep x)
(vectorp x)
.EE
.PP
Non\-predicate macros in \f[CR]lfe/include/cl.lfe\f[R] include:
.IP
.EX
(dolist ...)
(vector ...)
.EE
.SS Supplemental Clojure Functions
From LFE\[cq]s earliest days, it\[cq]s Lisp\-cousin Clojure (created
around the same time) has inspired LFE developers to create similar,
BEAM\-versions of those functions.
These were collected in a separate library and then expanded upon, until
eventually becoming part of the LFE standard library.
.PP
Function definition macros:
.IP
.EX
(clj:defn ...)
(clj:defn\- ...)
(clj:fn ...)
.EE
.PP
Threading macros:
.IP
.EX
(clj:\-> ...)
(clj:\->> ...)
(clj:as\-> ...)
(clj:cond\-> ...)
(clj:cond\->> ...)
(clj:some\-> ...)
(clj:some\->> ...)
(clj:doto ...)
.EE
.PP
Conditional macros:
.IP
.EX
(clj:if\-let ...)
(clj:iff\-let ...)
(clj:condp ...)
(clj:if\-not ...)
(clj:iff\-not ...)
(clj:when\-not ...)
(clj:not= ...)
.EE
.PP
Predicate macros:
.IP
.EX
(clj:atom? x)
(clj:binary? x)
(clj:bitstring? x)
(clj:bool? x)
(clj:boolean? x)
(clj:even? x)
(clj:false? x)
(clj:falsy? x)
(clj:float? x)
(clj:func? x)
(clj:function? x)
(clj:identical? x)
(clj:int? x)
(clj:integer? x)
(clj:map? x)
(clj:neg? x)
(clj:nil? x)
(clj:number? x)
(clj:odd? x)
(clj:pos? x)
(clj:record? x)
(clj:reference? x)
(clj:true? x)
(clj:tuple? x)
(clj:undef? x)
(clj:undefined? x)
(clj:zero? x)
.EE
.PP
Other:
.IP
.EX
(clj:str x)
(clj:lazy\-seq x)
(clj:conj ...)
(clj:if ...)
.EE
.PP
Most of the above mentioned macros are available in the \f[CR]clj\f[R]
include file, the use of which allows developers to forego the
\f[CR]clj:\f[R] prefix in calls:
.IP
.EX
(include\-lib \[dq]lfe/include/clj.lfe\[dq])
.EE
.SH Notes
.IP \[bu] 2
NYI \- Not Yet Implemented
.IP \[bu] 2
N.B.
\- Nota bene (note well)
.SH SEE ALSO
\f[B]lfe(1)\f[R], \f[B]lfescript(1)\f[R], \f[B]lfe_cl(3)\f[R]
.SH AUTHORS
Robert Virding.