quote — return a value unevaluated
quote — return a value unevaluated
quote suppresses evaluation and returns its argument as a raw Lion value. It is the primary way to produce an array or string literal that should not be treated as a function call or an environment reference.Syntax: ["quote", <expression>]Returns: the argument, unchanged.["number/add", 1, 2] — not 3."hello" regardless of whether "hello" is bound in the environment.eval — evaluate twice
eval — evaluate twice
eval evaluates its argument and then evaluates the result a second time. This allows a Lion program to construct an expression at runtime and immediately execute it.Syntax: ["eval", <expression>]Returns: the result of evaluating the produced expression.quote returns ["number/add", 1, 2].
Second pass: that array is evaluated as a function call, returning 3.Internally, evaluateEval validates the first-pass result against LionExpressionSchema before the second evaluation, so only valid Lion expressions can be double-evaluated.begin — sequential evaluation
begin — sequential evaluation
begin evaluates a sequence of expressions in order and returns the value of the last one. It is the standard way to execute side-effecting forms (such as define) before producing a final result.Syntax: ["begin", <expr1>, <expr2>, ..., <exprN>]Returns: the value of <exprN>.define forms in order, then resolves "x" — returns 2.42.define — bind a name in the global environment
define — bind a name in the global environment
define evaluates an expression and stores the result under a name in the toplevel (global) environment. The stored value is also returned, making define composable inside begin chains.Syntax: ["define", "<name>", <expression>]Returns: the evaluated value.42 under "answer" globally and returns 42."double". Later expressions can call it:10.lambda — create a lexically-scoped function
lambda — create a lexically-scoped function
lambda creates a Lion function. It captures the environment at definition time (lexical closure) and creates a fresh inner environment for each call, binding parameter names to the supplied arguments.Syntax: ["lambda", ["<param1>", "<param2>", ...], <body>]Returns: a JavaScript function that, when called, evaluates <body> in the captured scope extended with the argument bindings.12.Closures:15. The lambda closes over "base" through the environment chain.Lambdas also observe define mutations made after creation, because they walk the environment chain at call time rather than copying values at definition time.cond — conditional branching
cond — conditional branching
cond evaluates condition/result pairs in order and returns the result of the first pair whose condition is truthy. An optional else branch acts as a catch-all. If no condition matches and no else is present, cond returns null.Syntax:null."score" bound to 85, the second branch matches — returns "pass".Without else:null.Conditions are evaluated lazily: as soon as one returns a truthy value, subsequent conditions are not evaluated.match — structural pattern matching
match — structural pattern matching
match evaluates a value, tests it against a sequence of predicate/handler pairs, and calls the handler of the first matching pair with the value. The last argument is always a fallback handler that runs when no pattern matches.Syntax:Functional predicates
Any function that returns a boolean can be a predicate. The stdlibvalue/*? functions are designed for this:"value" bound to 42 (a number), the first branch matches — returns 43.
With "value" bound to "hi" (a string), the second branch matches — returns "hi!".
Anything else falls through to the identity fallback.Structural predicates
A predicate can also be a plain object whose keys must exist on the matched value and whose leaf values are predicates applied to the corresponding fields:- the value has a
"type"field that equals"user"(usingfunc/partialto applystring/equals?) - the value has a
"profile"object with a"name"field that is a string
"value/identity" is called with the whole value and it is returned unchanged.Structural predicates are evaluated recursively. A field value can itself be a structural predicate object, enabling deep pattern matching on nested data shapes without writing a ladder of
cond expressions.