Defines a function.
When a fn form is evaluated, it allocates and returns a new closure (a value which
belongs to the primitive type fn). Just like a Rust closure, this closure may capture
any local variables which are in scope. Each local variable may be simultaneously captured
by multiple closures.
(let counter (do
(let n 0)
(fn ()
(inc! n)
n)))
(prn (counter)) ; prints 1
(prn (counter)) ; prints 2
(prn n) ; an error: n is not in scope
If the same fn form is evaluated multiple times (for example, in a loop), it will
allocate a new closure each time.
params must be a valid array pattern. When the
function is called, all of its arguments are matched against params, and then its body
forms are evaluated as an "implicit do". It's an error if the call's arguments do not
match params - for example, because too few or too many arguments were provided.
(let f (fn (a b c) (prn a b c)))
(f 1 2) ; error: expected 3 or more arguments
The return or yield special forms can be used to return early
from the function call. Otherwise, the result of the function call is the evaluation
result of the body forms.
A fn form may specify one or more flags, listed immediately before params:
&name namespecifies the function's name, for debugging purposes.&arg-limits min maxspecifies a minimum and maximum argument count. When&arg-limitsis present, theparamspattern must only contain a single rest param,(..rest).minmust be an integer;maxmay be an integer or#n.