lfe_guide(7)           Miscellaneous Information Manual           lfe_guide(7)

NAME
       lfe_guide - Lisp Flavoured Erlang User Guide

SYNOPSIS
       Note: {{ ...  }} is used to denote optional syntax.

LITERALS AND SPECIAL SYNTACTIC RULES
   Integers
       Integers can be written in various forms and number bases:

       • Regular decimal notation:

           1234 -123 0

       • Binary notation:

           #b0 #b10101 #b-1100

       • Binary notation (alternative form):

           #*0 #*10101 #*-1100

       • Octal notation:

           #o377 #o-111

       • Explicitly decimal notation:

           #d1234 #d-123 #d0

       • Hexadecimal notation:

           #xc0ffe #x-01

       • Notation with explicit base (up to 36):

           #2r1010 #8r377 #36rhelloworld

       • Character  notation (the value is the Unicode code point of the char‐
         acter):

           #\a #\$ #\Ã¤

       • Character notation with the value in hexadecimal:

           #\x1f42d;

       In all these forms, the case of the indicating letter is  not  signifi‐
       cant, i.e. #b1010 and #B1010 are identical as are #16rf00 and #16Rf00.

       Similarly,  the  case is not significant for digits beyond 9 (i.e. ‘a’,
       ‘b’, ‘c’, ...  for number bases larger than  10),  e.g. #xabcd  is  the
       same  as #xABCD and can even be mixed in the same number, e.g. #36rHel‐
       loWorld is valid and the same number  as  #36Rhelloworld  and  #36rHEL‐
       LOWORLD.

       The character notation using hexadecimal code representation (#\x....;)
       is  basically  the same thing as the regular hexadecimal notation #x...
       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).

   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 num‐
       bers:

              1.0 +1.0 -1.0 1.0e10 1.111e-10

       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: 100. or .125.

   Strings
       There are two forms of strings: list strings and binary strings.

   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): “any text between double quotes where
       " and other special characters like \n can be escaped”.

       As  a  special  case you can also write out the character number in the
       form \xHHH; (where  “HHH”  is  an  integer  in  hexadecimal  notation),
       e.g. "\x61;\x62;\x63;" is a complicated way of writing "abc".  This can
       be convenient when writing Unicode letters not easily typeable or view‐
       able  with  regular  fonts.   E.g.  "Cat: \\x1f639;" might be easier to
       type (and view on output devices without a Unicode  font)  then  typing
       the actual Unicode letter.

   Binary Strings
       Binary strings are just like list strings but they are represented dif‐
       ferently  in  the  virtual  machine.  The simple syntax is #"...", e.g.
       #"This  is  a  binary  string  \n  with  some  \"escaped\"  and  quoted
       (\\x1f639;) characters"

       You can also use the general format for creating binaries (#B(...), de‐
       scribed  below), e.g. #B("a"), #"a", and #B(97) are all the same binary
       string.

   Character Escaping
       Certain control characters can be more readably included by using their
       escaped name:

                | Escaped name | Character       |
                |--------------+-----------------|
                | \b           | Backspace       |
                | \t           | Tab             |
                | \n           | Newline         |
                | \v           | Vertical tab    |
                | \f           | Form Feed       |
                | \r           | Carriage Return |
                | \e           | Escape          |
                | \s           | Space           |
                | \d           | Delete          |

       Alternatively you can also  use  the  hexadecimal  character  encoding,
       e.g. "a\nb" and "a\x0a;b" are the same string.

   Triple-quoted Strings
       LFE’s  triple-quote  strings are modelled on those in Erlang so we will
       use their description of them.

       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  verba‐
       tim,  that  is,  they do not allow escape sequences, and thereby do not
       need double quote characters to be escaped.

       Example, with verbatim double quote characters:

              """
                Line "1"
                Line "2"
                """

       That is equivalent to the normal single quoted string (which  also  al‐
       lows newlines):

              "Line \"1\"
              Line \"2\""

       The  opening and the closing lines have the delimiters: the ““” charac‐
       ters.  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.

       The indentation is defined by the white space character  sequence  pre‐
       ceding  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.

       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 syn‐
       tax error.

       Here is a larger example:

              """
                    First line starting with two spaces
                  Not escaped: "\t \r \xFF" and """

                  """

       That corresponds to the normal string:

              "  First line starting with two spaces
              Not escaped: \"\\t \\r \\xFF\" and \"\"\"
              "

       Binary strings can also be written as triple-quoted strings:

              #"""
                Line "1"
                Line "2"
                """

       which correspnds to the binary:

              #"Line \"1\"\nLine \"2\""

   Function References
       The function references are the forms:

              (function func-name arity)
              (function mod-name func-name arity)

       These forms evaluate to function references which can be used with fun‐
       call to call the functions.

       There is also a special syntax:

              #'func-name/arity
              #'mod-name:func-name/arity

       which is still supported but is deprecated.

   Binaries
       We have already seen binary strings, but the #B(...) 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.

       Example invocations are that show the various annotations:

              > #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((#"a" binary) (#"b" binary))
              #"ab"

       Learn more about “segments” of binary data e.g. in “Learn You Some  Er‐
       lang  ⟨http://learnyousomeerlang.com/starting‐out‐for‐real#bit‐syntax⟩”
       ⟨http://learnyousomeerlang.com/starting‐out‐for‐real#bit‐syntax⟩.

   Lists
       Lists are formed either as ( ... ) or [ ... ] where the  optional  ele‐
       ments  of the list are separated by some form or whitespace.  For exam‐
       ple:

              ()
              (the empty list)
              (foo bar baz)
              (foo
               bar
               baz)

   Tuples
       Tuples are written as #(value1 value2 ...).  The  empty  tuple  #()  is
       also valid.

   Maps
       Maps  are  written  as #M(key1 value1 key2 value2 ...) The empty map is
       also valid and written as #M().

   Structs
       Structs are written as #S(struct-name key1 value1 key2 value2 ...).

       Note that structs cannot  be  created  with  the  literal  syntax,  the
       (struct mod-name ...) form must be used.

   Symbols
       Things that cannot be parsed as any of the above are usually considered
       as a symbol.

       Simple  examples  are  foo, Foo, foo-bar, :foo.  But also somewhat sur‐
       prisingly 123foo and 1.23e4extra (but note that  illegal  digits  don’t
       make  a  number  a symbol when using the explicit number base notation,
       e.g. #b10foo gives an error).

       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.

       Of these, only |, \', ', ,, and # may not be the first character of the
       symbol’s name (but they are allowed as subsequent letters).

       I.e.  these are all legal symbols: foo, foo, Âµ#, Â±1, 451Â°F.

       Symbols  can be explicitly constructed by wrapping their name in verti‐
       cal bars, e.g. |foo|, |symbol name with spaces|.  In this case the name
       can contain any character of in the range from 0 to 255 (or even  none,
       i.e. ||  is a valid symbol).  The vertical bar in the symbol name needs
       to be escaped: |symbol with a vertical bar \| in its  name|  (similarly
       you will obviously have to escape the escape character as well).

   Comments
       Comments come in two forms: line comments and block comments.

       Line comments start with a semicolon (;) and finish with the end of the
       line.

       Block comments are written as #| comment text |# where the comment text
       may  span  multiple  lines  but  my  not contain another block comment,
       i.e. it may not contain the character sequence #|.

   Evaluation While Reading
       #.(... some expression ...).  E.g.  #.(+ 1 1) will evaluate the (+ 1 1)
       while it reads the expression and then be effectively 2.

Supported forms
   Core forms
              (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 ...)
              (andalso ... )
              (orelse ... )
              (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 ... )
              (prog1 ...)
              (prog2 ...)
              (if test true-expr {{false-expr}})
              (case e
                (pat {{(when e ...)}} ...)
                ... ))
              (cond (test body ...)
                    ...
                    ((?= pat expr) ...)
                    ...
                    (else ...))
              (maybe
                ...
                {{(else ((pat) {{(when e ...)}} ... )       - Else clauses
                       ...)}})
              (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)

   Basic macro forms
              (: mod func arg ... ) =>
                      (call 'mod 'func arg ... )
              (mod:func arg ... ) =>
                      (call 'mod 'func arg ... )
              (? {{timeout {{default}} }})
              (++ ... )
              (-- ... )
              (list* ... )
              (let* (... ) ... )
              (flet ((name (arg ...) {{doc-string}} ...)
                     ...)
                ...)
              (flet* (...) ... )
              (fletrec ((name (arg ...) {{doc-string}} ...)
                        ...)
                ...)
              (fun func arity)                              - Expand to lambdas
              (fun mod func arity)
              (lc (qual ...) expr)
              (list-comp (qual ...) expr)
              (bc (qual ...) bitstringexpr)
              (binary-comp (qual ...) bitstringexpr)
              (ets-ms ...)
              (trace-ms ...)

   Common Lisp inspired macros
              (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) ...)
                          ...)
                ...)
              (defmodule name ...)
              (defrecord name ...)
              (defstruct ...)

Patterns
       Written as normal data expressions where symbols are variables and  use
       quote  to match explicit values.  Binaries and tuples have special syn‐
       tax.

              {ok,X}                  -> (tuple 'ok x)
              error                   -> 'error
              {yes,[X|Xs]}            -> (tuple 'yes (cons x xs))
              <<34,U:16,F/float>>     -> (binary 34 (u (size 16)) (f float))
              [P|Ps]=All              -> (= (cons p ps) all)

       Repeated variables are supported in patterns and there is an  automatic
       comparison of values.

       _  as the “don’t care” variable is supported.  This means that the sym‐
       bol _, which is a perfectly valid symbol, can never  be  bound  through
       pattern matching.

       Aliases  are defined with the (= pattern1 pattern2) pattern.  As in Er‐
       lang patterns they can be used anywhere in a pattern.

       CAVEAT 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 re‐
       moved, but later passes of the compiler can’t handle this yet.

Guards
       Wherever a pattern occurs (in let, case, receive, lc, etc.)  it can  be
       followed  by  an  optional  guard  which  has the form (when test ...).
       Guard tests are the same as in vanilla Erlang and can contain the  fol‐
       lowing guard expressions:

              (quote e)
              (cons gexpr gexpr)
              (car gexpr)
              (cdr gexpr)
              (list gexpr ...)
              (tuple gexpr ...)
              (tref gexpr gexpr)
              (binary ...)
              (map ...)
              (msiz ...) (map-size ...)
              (mref ...) (map-get ...)
              (mset ...) (map-set ...)
              (mupd ...) (map-update ...)
              (record ...)                - Also the macro versions
              (is-record ...)
              (record-index ...)
              (record-field ...)
              (is-struct ...)
              (struct-field ...)
              (type-test e)               - Type tests
              (guard-bif ...)             - Guard BIFs, arithmetic,
                                            boolean and comparison operators

       An  empty  guard,  (when),  always  succeeds  as there is no test which
       fails.  This simplifies writing macros which handle guards.

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:

              (defun max (x y)
                "The max function."
                (if (>= x y) x y))

       Optional comments are also allowed in match style functions  after  the
       function name and before the clauses:

              (defun max
                "The max function."
                ((x y) (when (>= x y)) x)
                ((x y) y))

       This  is also possible in a similar style in local functions defined by
       flet and fletrec:

              (defun foo (x y)
                "The max function."
                (flet ((m (a b)
                         "Local comment."
                         (if (>= a b) a b)))
                  (m x y)))

Variable Binding and Scoping
       Variables are lexically scoped and bound by  lambda,  match-lambda  and
       let  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 vari‐
       ables are exported out of the form.  So for example the following func‐
       tion:

              (defun foo (x y z)
                (let ((x (zip y)))
                  (zap x z))
                (zop x y))

       The  variable  y in the call (zip y) comes from the function arguments.
       However, the x bound in the let will shadow the x from the arguments so
       in the call (zap x z) the x is bound in the let while the z comes  from
       the  function arguments.  In the final (zop x y) both x and y come from
       the function arguments as the let does not export x.

Function Binding and Scoping
       Functions are lexically scoped and bound by the top-level defun and  by
       the  macros  flet  and fletrec.  LFE is a Lisp-2 so functions and vari‐
       ables 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 (funcall func-var arg ...) is re‐
       quired to call lambda/match-lambda bound to a variable  or  used  as  a
       value.

       Unqualified  functions shadow as stated above which results in the fol‐
       lowing order within a module, outermost to innermost:

       • Predefined Erlang BIFs

       • Predefined LFE BIFs

       • Imports

       • Top-level defines

       • Flet/fletrec

       • Core forms, these can never be shadowed

       This means that it is  perfectly  legal  to  shadow  BIFs  by  imports,
       BIFs/imports  by top-level functions and BIFs/imports/top-level by fle‐
       trecs.  In this respect there is nothing special about BIFs, they  just
       behave  as  predefined imported functions, a whopping big (import (from
       erlang ...)).  EXCEPT that we know  about  guard  BIFs  and  expression
       BIFs.   If  you  want  a private version of spawn then define it, there
       will be no warnings.

       CAVEAT This does not hold for the supported core forms.  These  can  be
       shadowed  by  imports or redefined but the compiler will always use the
       core meaning and never an alternative.  The  compiler  will  warn  when
       core forms are redefined but it is not an error.

Module definition
       The  basic  forms  for defining a module and extending its metadata and
       attributes are:

              (define-module name meta-data attributes)
              (extend-module meta-data attributes)

       The valid meta data is (type typedef ...), (opaque typedef ...),  (spec
       function-spec  ...)  and (record record-def ...).  Each can take multi‐
       ple definitions in one meta form.

       Attributes declarations have the syntax (attribute value-1  ...)  where
       the attribute value is a list off the values in the declaration

       To simplify defining modules there is a predefined macro:

              (defmodule name
                "This is the module documentation."
                (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 ...)
                ... )

       We  can have multiple export and import attributes within module decla‐
       ration.  The (export all) attribute is allowed together with other  ex‐
       port  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 module_info/0-1 functions.

       In  the import attribute the (from mod (f1 2) ...)  means that the call
       (f1 'everything 42) will  be  converted  by  the  compiler  to  (mod:f1
       'everything  42))  while  the (rename mod ((g2 2) m-g1) ...) means that
       the call (m-g1 'everything 42) will be converted to (mod:g1 'everything
       42).  The rename form can be used as compact way of indicating the  im‐
       ported function’s module.  Note that when importing a module

       • the compiler does no checking on that module at all

       • in  the rename above the functions g1/2 and g2/1 aren’t automatically
         imported, only the “renamed” functions.

       • we do not really see in the code that we are calling  a  function  in
         another module

       In the module-alias attribute the (really-long-module-name rlmn) decla‐
       ration  means that the call (lrmn:foo 'everything 42) will be converted
       by the compiler to (really-long-module-name:foo 'everything 42).   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  import as it does not hide that we are calling a function in an‐
       other module.

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.

       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:

              (define-macro name meta-data lambda|match-lambda)
              (let-macro ((name lambda|match-lambda)
                ...)

       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 vari‐
       able 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 | - foo - | which no one
       in their right mind would use.

       To simplify writing macros there are a number of predefined macros:

              (defmacro name (arg ...) ...)
              (defmacro name arg ...)
              (defmacro name ((argpat ...) body) ...)

       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 argu‐
       ment list.  For example:

              (defmacro double (a) `(+ ,a ,a))
              (defmacro my-list args `(list ,@args))
              (defmacro andalso
                ((list e) `,e)
                ((cons e es) `(if ,e (andalso ,@es) 'false))
                (() `'true))

       The macro definitions in a macrolet obey the same rules as defmacro.

       The macro functions created by defmacro and macrolet automatically  add
       the  second  argument  with the current macro environment with the name
       $ENV.  This allows explicit expansion of macros inside  the  macro  and
       also manipulation of the macro environment.  No changes to the environ‐
       ment are exported outside the macro.

       User  defined  macros shadow the predefined macros so it is possible to
       redefine the built-in macro definitions.  However, see the  caveat  be‐
       low!

       Yes,  we have the backquote.  It is implemented as a macro so it is ex‐
       panded at macro expansion time.

       Local functions that are only available at  compile  time  and  can  be
       called by macros are defined using eval-when-compile:

              (defmacro foo (x)
                ...
                (foo-helper m n)
                ...)

              (eval-when-compile
                (defun foo-helper (a b)
                  ...)

                )

       There can be many eval-when-compile forms.  Functions defined within an
       eval-when-compile  are  mutually recursive but they can only call other
       local functions defined in an earlier eval-when-compile and macros  de‐
       fined  earlier  in  the  file.   Functions defined in eval-when-compile
       which are called by macros can defined after the macro but must be  de‐
       fined before the macro is used.

       Scheme’s  syntax  rules are an easy way to define macros where the body
       is just a simple expansion.  The are implemented the the module scm and
       are supported with scm:define-syntax and scm:let-syntax and the equiva‐
       lent scm:defsyntax and scm:syntaxlet.  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:

              (scm:defsyntax andalso
                (() 'true)
                ((e) e)
                ((e . es) (case e ('true (andalso . es)) ('false 'false))))

       There is an include file “include/scm.lfe” which defines macros so  the
       names don’t have to be prefixed with scm:.

       CAVEAT  While  it  is  perfectly legal to define a Core form as a macro
       these will silently be ignored by the compiler.

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:

              (defmacro double (a)
                "Double macro."
                `(+ ,a ,a))

       Optional comments are also allowed in  match  style  macros  after  the
       macro name and before the clauses:

              (defmacro my-list args
                "List of arguments."
                `(list ,@args))

              (defmacro andalso
                "The andalso form."
                ((list e) `,e)
                ((cons e es) `(if ,e (andalso ,@es) 'false))
                (() `'true))

       This  is also possible in a similar style in local functions defined by
       macrolet:

              (defun foo (x y)
                "The max function."
                (macrolet ((m (a b)
                             "Poor macro definition."
                             `(if (>= ,a ,b) ,a ,b)))
                  (m x y)))

Records
       Records are tuples with the record name as first element and  the  rest
       of  the  fields in order exactly like “normal” Erlang records.  As with
       Erlang records the default default value is the atom ‘undefined’.

       The basic forms for defining a record, creating, accessing and updating
       it are:

              (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 ...)

       Note that the list of field/value  pairs  when  making  or  updating  a
       record is a flat list.

       Note  that the old make-record form has been deprecated and is replaced
       by record which better matches other constructors like tuple  and  map.
       It still exists but should not be used.

       We  will explain these forms with a simple example.  To define a record
       we do:

              (define-record person
                             ((name "")
                              (address "" (string))
                              (age)))

       which defines a record person with the fields name (default value  ""),
       address  (default  value "" and type (string)) and age.  To make an in‐
       stance of a person record we do:

              (record person name "Robert" age 54)

       The record form is also used to define a pattern.

       We can get the value of the address field in a person record and set it
       by doing (the variable robert references a person record):

              (record-field robert person address)
              (record-update robert person address "my home" age 55)

       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 al‐
       ways literal atoms.

       To simplify defining and using records there is a predefined macro:

              (defrecord name
                (field) | field
                (field default-value)
                (field default-value type)
                ... )

       This will create access macros for record creation  and  accessing  and
       updating  fields.   The  make-, match- and update- forms takes optional
       argument pairs field-name value to get non-default values.  E.g.  for

              (defrecord person
                (name "")
                (address "" (string))
                (age))

       the following will be generated:

              (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)

       • (make-person name "Robert" age 54) - Will create a new person  record
         with  the name field set to “Robert”, the age field set to 54 and the
         address field set to the default ““.

       • (match-person name name age 55) - 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.

       • (is-person john) - Test if john is a person record.

       • (person-address john) - Return the address field of the person record
         john.

       • (person-address)  - Return the index of the address field of a person
         record.

       • (update-person-address john "back  street")  -  Updates  the  address
         field of the person record john to “back street”.

       • (update-person  john  age  35 address "front street") - In the person
         record john update the age field to  35  and  the  address  field  to
         “front street”.

       • (fields-person)  -  Returns a list of fields for the record.  This is
         useful for when using LFE with Mnesia,  as  the  record  field  names
         don’t have to be provided manually in the create_table call.

       • (size-person) - Returns the size of the record tuple.

       Note that the older now deprecated set- forms are still generated.

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.

              (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 ...)

       We will explain these forms with a simple example.  To define a  struct
       we do:

              (define-struct ((name "")
                              (address "" (string))
                              (age)))

       which  defines  a  struct  with the name of the current module with the
       fields name (default value ""), address  (default  value  ""  and  type
       (string)) and age.  To make an instance of struct we do:

              (struct mod-name name "Robert" age 54)

       The struct form is also used to define a pattern.

       We  can  get the value of the address field in the struct and set it by
       doing (the variable robert references a struct):

              (struct-field robert mod-name address)
              (struct-update robert mod-name address "my home" age 55)

       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.

       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  al‐
       ways literal atoms.

Binaries/bitstrings
       A binary is

              (binary seg ... )

       where seg is

                  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)

       val  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  inte‐
       gers these are also valid here.  In a binary constant all literal forms
       are allowed on input but they will always be written as bytes.

Maps
       A map is created with:

              (map key value ... )

       To access maps there are the following forms:

       • (map-size map) - Return the size of a map.

       • (map-get  map  key) - Return the value associated with the key in the
         map.

       • (map-set map key val ... ) - 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.

       • (map-update map key val ... ) - Update the keys in the map to values.
         Note that this form requires all the keys to  already  exist  in  the
         map.

       • (map-remove map key ... ) - Remove the keys in the map.

       There  are  also  alternate short forms msiz, mref, mset, mupd and mrem
       based on the Maclisp array reference forms.  They take the  same  argu‐
       ments as their longer alternatives.

Core forms
   If
       The  LFE if is more like a classic if than the Erlang if.  For the test
       it allows any Erlang boolean expression which must return  either  true
       or  false.  The false expression is optional and if it not included the
       if returns false.  Some examples:

              (if (our-test) (it-was-true))

              (if (our-test) (it-was-true) (it-was-false))

   Cond
       The LFE cond is similar to if and tests in cond  are  Erlang  tests  in
       that they should return either true or false.  If no test succeeds then
       the  cond does not generate an exception but just returns false.  There
       is a simple catch-all “test” else which must last and can  be  used  to
       handle the case when all tests fail.

       Cond has been extended with the extra test (?= pat expr) which tests if
       the  result  of expr matches the pattern pat.  If so it binds the vari‐
       ables in pat which can be used in the cond test body expression.  A op‐
       tional guard is allowed here.  An example:

              (cond ((foo x) ...)
                    ((?= (cons x xs) (when (is_atom x)) (bar y))
                     (fubar xs (baz x)))
                    ((?= (tuple 'ok x) (baz y))
                     (zipit x))
                    ...
                    (else 'yay))

   Maybe
       LFE has an Erlang compatible maybe.  It has the same  features  as  the
       Erlang  maybe  with  the  ?= operator and else.  The expressions in the
       maybe block are evaluated sequentially:

              (maybe
                expr-1
                expr-2
                ...
                expr-n)

       If all the expressions succeed then maybe block returns  the  value  of
       expr-n.  The conditional match

              (?= pattern expr)

       can  short  circuit  this.  If the match succeeds then the variables in
       pattern become bound.  The ?= match returns the value  of  the  expres‐
       sions.   If  the  match  fails  then the rest of the expressions in the
       maybe block are skipped and maybe returns the value of the expr.

       The maybe block can be augmented with else clauses:

              (maybe
                expr-1
                ...
                expr-n
                (else
                  ((pattern-1) body-1)
                  ...
                  ((pattern-n) (when guard-test) body-n)
                ))

       If a conditional match fails  then  the  value  of  the  expression  is
       matched  against  the  patterns in the else claueses and if one matches
       then its body is evaluated.  Guard tests are allowed.   If  no  pattern
       matches then an else-clause run-time error occurs.

       An example:

              (maybe
                (foo g)
                (?= `#(ok ,a) (a g))
                (bar g)
                (?= `#(ok ,b) (b g))
                (+ a b)
                (else
                  (('error) 1 #(got error))
                  (('wrong) 2 #(got wrong))
                ))

       The  maybe body can include ?= forms which behave in the same way as in
       the Erlang maybe.  As LFE cannot bind variables in the same way  as  in
       Erlang we allow let in the body to bind variables.  These variables are
       only  local in the let body so this body is “lifted” upto the top level
       maybe body and so can contain ?= forms as well.

   List/binary comprehensions
       List/binary comprehensions are supported as  macros.   The  syntax  for
       list comprehensions is:

              (lc (qual  ...) expr)
              (list-comp (qual  ...) expr)

       where the last expr is used to generate the elements of the list.

       The syntax for binary comprehensions is:

              (bc (qual  ...) bitstringexpr )
              (binary-comp (qual  ...) bitstringexpr)

       where  the final expr is a bitstring expression and is used to generate
       the elements of the binary.

       The supported qualifiers, in both list/binary comprehensions are:

              (<- pat {{guard}} list-expr)        - Extract elements from list
              (<= bin-pat {{guard}} binary-expr)  - Extract elements from binary
              expr                                - Normal boolean test

       Some examples:

              (lc ((<- v (when (> v 5)) l1)
                   (== (rem v 2) 0))
                v)

       returns a list of all the even  elements  of  the  list  l1  which  are
       greater than 5.

              (bc ((<= (binary (f float (size 32))) b1)
                   (> f 10.0))
                (progn
                  (: io fwrite "~p\n" (list f))
                  (binary (f float (size 64)))))

       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 num‐
       bers are first printed.

       This could also be written using a guard for the test:

              (bc ((<= (binary (f float (size 32))) (when (> f 10.0)) b1))
                (progn
                  (: io fwrite "~p\n" (list f))
                  (binary (f float (size 64)))))

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:

              (ets-ms
                ((arg ... ) {{(when e ...)}} ...)             - Matches clauses
                ... )

       For example:

              (ets:select db (ets-ms
                               ([(tuple _ a b)] (when (> a 3)) (tuple 'ok b))))

       It is a macro which creates the match specification structure which  is
       used  in  ets:select  and  mnesia:select.   For  tracing instead of the
       ets-ms macro there is the trace-ms macro which is also used in conjunc‐
       tion with the dbg module.  The same restrictions as to what can be done
       apply as for vanilla match specifications:

       • There is only a limited number of BIFs which are allowed

       • There are some special functions only for use with dbg

       • For ets/mnesia it takes a single parameter which must a  tuple  or  a
         variable

       • For dbg it takes a single parameter which must a list or a variable

       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.

       Macros, especially record macros,  can  freely  be  used  inside  match
       specs.

       CAVEAT  Some  things which are known not to work in the current version
       are andalso, orelse and record updates.

   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 qlc:q([...]).  The handle can be  used  together  with
       all the combination functions in the module qlc.

       For example:

              (qlc (lc ((<- (tuple k v) (: ets table e2)) (== k i)) v)
                   {{Option}})

       Macros,  especially record macros, can freely be used inside query list
       comprehensions.

       CAVEAT Some things which are known not to work in the  current  version
       are nested QLCs and let/case/recieve which shadow variables.

Predefined LFE functions
       The following more or less standard lisp functions are predefined:

              (<arith_op> expr ...)
              (<comp_op> expr ...)

       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 eval‐
       uate ALL their arguments before doing the arithmetic/comparisons opera‐
       tions.

              (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)

       The standard association list functions.

              (subst new old tree)
              (subst-if new test tree)
              (subst-if-not new test tree)
              (sublis alist tree)

       The standard substitution functions.

              (macroexpand-1 expr {{environment}})

       If Expr is a macro call, does one round of expansion, otherwise returns
       Expr.

              (macroexpand expr {{environment}})

       Returns the expansion returned  by  calling  macroexpand-1  repeatedly,
       starting with Expr, until the result is no longer a macro call.

              (macroexpand-all expr {{environment}})

       Returns  the  expansion  from the expression where all macro calls have
       been expanded with macroexpand.

       NOTE that when no explicit environment is given the  macroexpand  func‐
       tions  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.

              (eval expr {{environment}})

       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.

       For example if the data we wish to evaluate is in the variable expr and
       it assumes there is a local variable “foo” which  it  needs  to  access
       then we could evaluate it by calling:

              (eval `(let ((foo ,foo)) ,expr))

   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 'true and 'false.  Otherwise the
       definitions closely follow the CL definitions and won’t  be  documented
       here.

              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  'initial-value  x
              cl:reduce  function  sequence  'from-end  'true
              cl:reduce  function  sequence  'initial-value  x  'from-end  '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

       Furthermore,  there  is  an  include file which developers may which to
       utilize in  their  LFE  programs:  (include-lib  "lfe/include/cl.lfe").
       Currently  this  offers  Common  Lisp predicates, but may include other
       useful macros and functions in  the  future.   The  provided  predicate
       macros wrap the various is_* Erlang functions; since these are expanded
       at compile time, they are usable in guards.  The include the following:

              (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)

       Non-predicate macros in lfe/include/cl.lfe include:

              (dolist ...)
              (vector ...)

   Supplemental Clojure Functions
       From  LFE’s earliest days, it’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.

       Function definition macros:

              (clj:defn ...)
              (clj:defn- ...)
              (clj:fn ...)

       Threading macros:

              (clj:-> ...)
              (clj:->> ...)
              (clj:as-> ...)
              (clj:cond-> ...)
              (clj:cond->> ...)
              (clj:some-> ...)
              (clj:some->> ...)
              (clj:doto ...)

       Conditional macros:

              (clj:if-let ...)
              (clj:iff-let ...)
              (clj:condp ...)
              (clj:if-not ...)
              (clj:iff-not ...)
              (clj:when-not ...)
              (clj:not= ...)

       Predicate macros:

              (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)

       Other:

              (clj:str x)
              (clj:lazy-seq x)
              (clj:conj ...)
              (clj:if ...)

       Most of the above mentioned macros are available  in  the  clj  include
       file,  the  use of which allows developers to forego the clj: prefix in
       calls:

              (include-lib "lfe/include/clj.lfe")

Notes
       • NYI - Not Yet Implemented

       • N.B.  - Nota bene (note well)

SEE ALSO
       lfe(1), lfescript(1), lfe_cl(3)

AUTHORS
       Robert Virding.

                                   2008-2020                      lfe_guide(7)
