-
Notifications
You must be signed in to change notification settings - Fork 1
Anonymous function
Note: the syntax described on this page is available from GeoDMS version 20.9.0 and later.
An anonymous function (also called a function literal or lambda) is a function written without a name, directly in the place where it is used. It carries the same typed header as a named function — a parameter telescope, an optional type-variable clause, a result type and a body — but no identifier of its own. Anonymous functions are a parse-time convenience: the engine turns each literal into an ordinary function item behind the scenes, so nothing new happens at calculation time.
Use an anonymous function when a small piece of logic is needed exactly once — typically as an argument to a higher-order function such as compose, where naming it separately would only add clutter.
The simplest form binds a literal to an item name with :=. The declared item is the function:
twice := function<V: numerics, D: domains>(attribute<V> x (D)) -> attribute<V> (D) := x + x;
This is the untyped name := function … spelling. A trailing ; after the body is tolerated, because the form reads like an assignment. When the body is a block rather than a := expr, the result is designated by name — the block must contain an item named result (or the declared result name):
ratio := function(attribute<float64> flw (Road); attribute<float64> cap (Road)) -> attribute<float64> (Road)
{
attribute<float64> raw (Road) := flw / cap;
attribute<float64> result (Road) := min_elem(raw, 1.0);
};
A function's own result may itself be an anonymous function, written after the ->. This replaces the older nested function result(…) idiom:
function compose3<V: numerics, D: domains>(f: nuf<V, D>; g: nuf<V, D>) -> nuf<V, D>
:= function(attribute<V> x (D)) -> attribute<V> (D) := f(g(x));
A result-position literal requires a -> function or signature-typed result; it is rejected under a plain data result type.
Anonymous functions may also appear inside a parenthesised expression. Two placements are supported.
Argument position — a literal passed straight to a call. A literal may carry its own type-variable clause; its extent runs to the separating comma:
attribute<float64> a (Road)
:= compose(function<W: numerics, E: domains>(attribute<W> y (E)) -> attribute<W> (E) := y + 1.0, sqr)(Road/flow);
A parenthesised group, applied immediately — the literal is wrapped in parentheses and called at once:
attribute<float64> b (Road)
:= (function(attribute<float64> z (Road)) -> attribute<float64> (Road) := 3.0 * z)(Road/flow);
In both cases the literal is lifted at parse time into a hidden sibling declaration at exactly its lexical position, so ordinary scoping and capture apply. Two textually identical literals applied to the same arguments reduce to the same item, so applicative identity is preserved.
Because := expr { … } could read either as a literal with a body block or as the declared item's own sub-item block, GeoDMS adopts a single rule:
An unbracketed
{following a calculation rule always opens the declared item's sub-item block. Braces are expression content only when enclosed — directly or transitively — in parentheses.
So a brace block can belong to a function literal only inside a call's argument list or an explicitly parenthesised expression. At the top level of a rule, a { always starts the item's own sub-items, never a lambda body. This keeps the rule-extent trivial (an expression ends at any top-level {) and is backward compatible, since no pre-existing expression contained a top-level brace.
A direct consequence: a bare, unparenthesised literal is not a valid expression for a typed data item. The following is rejected — use the untyped whole-rule form name := function … instead:
// rejected: unparenthesised literal as the whole rule of a typed data item
attribute<float64> bad (Road) := function(attribute<float64> x (Road)) -> attribute<float64> (Road) := x + x;
In this first version an anonymous function literal:
- carries no
usingclause, and - has no named result of its own (the result is given by
:= expr, or designated by name from a body block).
Named functions with these features are written with the full function construct.
20.9.0
GeoDMS ©Object Vision BV. Source code distributed under GNU GPL-3. Documentation distributed under CC BY-SA 4.0.