Lambdas
Level:
nelumbo.logic. Available afterimport nelumbo.logic, or transitively through any package (nelumbo.integersand up).
A lambda is an anonymous expression over bound variables: [x](x>0). Lambdas are declared in logic.nl (they used to live in lang.nl and moved to the logic level on 2026-10-05) because the quantifiers E[…](…) and A[…](…) are lambdas, and because the collection operations where, map, sort and set-builder {[e](c)} take them as arguments.
Syntax
Lambda1<A1,R> ::= [ <{Variable,A1}> ] ( <R#0> ) @nelumbo.logic.Lambda
Lambda2<A1,A2,R> ::= [ <{Variable,A1}> , <{Variable,A2}> ] ( <R#0> ) @nelumbo.logic.Lambda
… (up to Lambda6)
(abbreviated; see logic.nl for all six.)
[ … ]lists the bound variables, comma-separated. Each hole is typed{Variable,A1}: it must be a variable (an already declared one such asInteger i) and of the matching argument type. Anything else is a parse error.( … )is the body, an expression of result typeR(precedence#0, so everything up to the closing parenthesis belongs to it).Ris the lambda's result type. A lambda whose body isBooleanis a predicate; one whose body is anIntegeris a function toInteger.
Integer i, ib, ia
[i](i>1) ▸ Lambda1<Integer,Boolean> — a predicate over one Integer
[i](i*i) ▸ Lambda1<Integer,Integer> — a function Integer → Integer
[ib,ia](ib<ia) ▸ Lambda2<Integer,Integer,Boolean> — a binary relation
Types
Type A1, A2, A3, A4, A5, A6, R
Lambda :: Object
Lambda<R> :: Lambda
Lambda1<A1,R> :: Lambda<R>
Lambda2<A1,A2,R> :: Lambda<R>
…
Lambda6<A1,A2,A3,A4,A5,A6,R> :: Lambda<R>
The arity-N type is LambdaN<A1,…,AN,R>, with N from 1 to 6 (a seventh variable is a parse error). All of them are subtypes of Lambda<R>, so a pattern that accepts any arity with a given result type can use <Lambda<R>> — the quantifiers do exactly that:
Boolean ::= ELambda<Boolean> @nelumbo.logic.ExistentialQuantifier,
ALambda<Boolean> @nelumbo.logic.UniversalQuantifier
E[x,y](p) is therefore the keyword E followed by a Lambda2<…,Boolean> literal — the quantifiers need no syntax of their own, and take the same one-to-six variables as a lambda.
Scope
The variables in [ … ] are local to the lambda: inside the body they take on the lambda's role instead of their outer one, and they are not visible outside it. This is the same scoping the quantifiers always had. The variable's declaration is still the ordinary one (Integer i); a lambda does not declare variables, only binds them.
Integer i
{[i](|i|=10)} = s // i is bound by the lambda; an outer i is untouched
Using lambdas
Lambdas are values consumed by natives. The language has no call syntax for a lambda: you cannot write f(3) for a lambda f. A lambda gets applied when it is an argument of a functor whose native implementation evaluates it — Lambda.test(…) for predicates (where, sort) and Lambda.apply(…) for functions (map). Declaring your own lambda-taking functor works the same as for any argument type:
Boolean ::= holds(Lambda1<Integer,Boolean>, Integer)
but its semantics must come from a native class (@nelumbo.…) that evaluates the lambda; a plain <=> rule can only pass the lambda along or ignore it. Library users normally meet lambdas through:
| Use | Lambda type | Defined in |
|---|---|---|
E[x](p), A[x,y](p) |
Lambda<Boolean> |
nelumbo.logic |
{[e](c)} |
Lambda1<E,Boolean> |
nelumbo.collections |
c where [x](p) |
Lambda1<E,Boolean> |
nelumbo.collections |
c map [x](expr) |
Lambda1<F,E> |
nelumbo.collections |
c sort [a,b](p) |
Lambda2<E,E,Boolean> |
nelumbo.collections |
Evaluation
For a predicate lambda, test instantiates the body with the argument values and asks the reasoner for a definite answer; for a function lambda, apply solves body = r for a fresh result variable r and takes the value. If the reasoner cannot reach a definite answer for some element (the body depends on something unbound, or recursion overflows), the whole surrounding operation reports an incomplete result instead of guessing — see three-valued-logic.md.
Native class
nelumbo.logic.Lambda (Node) backs all six functors. It keeps the list of bound variables and the body, and offers test(Object…) (a Boolean-body lambda; true only when definitely true) and apply(Object…) (the value of a function body). See native-classes.md.
See also
index.md—E[…](…)/A[…](…)collections.md—where,map,sort, set-builderlogicTest.nlandcollectionsTest.nl— executable specifications