Macros
A macro gives a title to reusable expression syntax. Expansion replaces a call with its template before compilation. The expanded expression follows the expression type and cost rules.
#_ada {name Ada
role engineer
age 36}
#_bob {name Bob
role engineer
age 41
mentor {#link #_ada}}
#_cy {name Cy
role designer
age 29}
Define a macro
A macro document has ordered params and an expands template. An optional
description explains its purpose. A stored definition has a title. The native macro builder also accepts an authored definition without saving it.
description Multiply an amount by a rate.
params [amount rate]
expands [* {insert amount} {insert rate}]
Parameter names are plain text. Each name must differ from the other names. A name cannot be empty or contain whitespace. A macro cannot have a built-in operator's title. Definition validation rejects unknown fields, missing required fields and invalid markers.
Call a macro
A call has the title first, then one argument for each declared parameter.
[pricing/apply-rate ?subtotal 0.2]
- subtotal
- 100.0
20.0
Expansion produces [* ?subtotal 0.2]. The variable remains a caller input.
Expansion rejects an invalid argument count.
[pricing/apply-rate 100.0]
Error
Invalid_Call
Insert and spread
An insertion marker is a map with one member. {insert name} replaces the
marker with one argument tree. {spread name} inserts each item of a list
argument into the surrounding list.
params [values]
expands [+ {spread values}]
[sum-all [1 2 3 4]]
10
The expansion is [+ 1 2 3 4]. A spread marker needs a surrounding list and a
list argument. An insertion preserves a list or map as one argument tree.
Compose macros
A template can call another macro. Expansion resolves nested calls before the compiler validates operators and types. Expansion rejects direct and indirect cycles.
params [value floor]
expands [>= {insert value} {insert floor}]
params [value]
expands [and [at-least {insert value} 18] [< {insert value} 65]]
[working-age 36]
true
quote stops macro expansion inside its values. The expression evaluator still
rejects quote. Syntax preserved during expansion is not necessarily executable.
Use macros in queries
A query expands macros in expression positions, including predicates, derivations, computed columns, grouping filters, ordering and projection. Ordinary fact values remain data.
find [?name]
where [[?person age ?age]
[?person name ?name]
[working-age ?age]]
orderBy [?name]
[{name Ada} {name Bob} {name Cy}]A mutation uses the same expansion rules in its selection query.
Current and pinned definitions
An unpinned call uses the current title mapping. Each accepted update records a mapping revision. A pin names that mapping revision, rather than the macro entity or its definition revision.
This update changes working-age to require an age of at least 40.
params [value]
expands [and [>= {insert value} 40] [< {insert value} 65]]
[working-age 36]
false
The first recorded mapping revision of working-age is 13 in this fresh
fixture. Read the actual revision from the saved definition in your database.
A pinned call keeps that earlier rule.
[
{title working-age
mappingRevision 13}
36]
true
A query can pin all calls of a title with its definitions member. Expansion
consumes that metadata before query compilation.
definitions {working-age 13}
find [?name]
where [[?person age ?age]
[?person name ?name]
[working-age ?age]]
orderBy [?name]
[{name Ada} {name Bob} {name Cy}]Expansion rejects an unknown mapping revision. It does not select the current rule.