Chapter 3:
Special Forms

Special forms are language constructs. They look like application expressions, but have special evaluation rules, which are invoked by the bindings of the keywords.

Local Variables

let:[ Eformals Eactuals Ebody ]
rec:[ Eformals Eactuals Ebody ]
fix:[ Eformals ! Eactuals ]
Local variables (besides function parameters) are declared by special expressions that declare the variables, define initial values for them and delineate their scope. Daisy has three such forms: let, rec and fix. In all three forms, Eformals is an identifier or an arbitrarily nested list of identifiers, and Eactuals is an expression that evaluates to a conforming structure containing bindings (initial values) for the variables. In let and rec, the expression Ebody is evaluated in the extended scope containing the new local variables and the result is returned as the value of the entire expression.

Here are some examples:

let:[a 3 add:[a a]]
let:[[x y] [fib:n fib:dcr:n] add:[x y]]
let:[[C ! Cs] (map:foo):s [C C ! Cs]]
The rec form differs from let in that Eactuals.is evaluated in the same scope as Ebody. This allows various kinds of mutually recursive or circular references to be created. fix is similar to rec, but returns the result of evaluating Eactuals. Fix is typically used when the sole purpose of the form is to create self-referential or circular structures.

Conditionals

if:[ Econd Ethen ]
if:[ Econd Ethen Eelse ]
if:[ Econd1 Ethen1 ... EcondN EthenN ]
if:[ Econd1 Ethen1 ... EcondN EthenN Eelse ]
The if form is a multi-way short-circuit conditional. The subexpressions Econd1, Econd2, etc. are evaluated sequentially from left to right; if one of them evaluates to a non-nil value the corresponding Ethen expression is evaluated and returned as the result. An optional Eelse expression can be provided at the end in case none of the Econd expressions is non-nil. If all the conditional subexpressions are false and there is no else expression then the value of the if conditional is nil.

Sequencing evaluation

seq:[E0 E1 ... En] => Vn
The seq form is a multi-way short-circuit conditional. The subexpressions Econd1, Econd2, etc. are evaluated sequentially from left to right; if one of them evaluates to a non-nil value the corresponding Ethen expression is evaluated and returned as the result. An optional Eelse expression can be provided at the end in case none of the Econd expressions is non-nil. If all the conditional subexpressions are false and there is no else expression then the value of the if conditional is nil.

Boolean operators

any?:[E0 E1 ... ] => Vi
all?:[E0 E1 ... ] => true or []
The begin form is a multi-way short-circuit conditional. The subexpressions Econd1, Econd2, etc. are evaluated sequentially from left to right; if one of them evaluates to a non-nil value the corresponding Ethen expression is evaluated and returned as the result. An optional Eelse expression can be provided at the end in case none of the Econd expressions is non-nil. If all the conditional subexpressions are false and there is no else expression then the value of the if conditional is nil.