Special Forms

In Scheme some forms are not handled as plain function application. This document lists the planned special forms for the language, along with their implementation status.

The set of forms are derived from those in R7RS.

Lambda Expressions

(lambda <formals> <expression>+)

Returns an anonymous procedure which binds its arguments to <formals> and then evaluates a number of <expression>s in the new environment.

Formals can be either a single identifier to bind the parameter list to, or a list which the parameters should be matched against. If the list contains . then following parameters are bound to a list to following argument.

e.g.:

The expression (lambda a (+ 1 2)) defines a procedure that takes any arguments and binds the list to a in the lambda’s environment.

The expression (lambda (b) (+ 1 2)) defines a procedure that takes a single argument and binds that to b in the lambda’s environment.

The expression (labmda (c . d) (+ 1 2)) defines a procedure that takes a single argument and an optional number of following arguments. The first argument is bound to c in the lambda’s environment and all remaining arguments are bound to a list d in the lambda’s environment.

Implementation status

All forms are lambdas are bound and lowered. Lambdas are implemnted as instances of Func<object[],object>. Implementation was live-streamed. Checkout YouTube for the stream archive.

Lexical Bindings

(let (<init>+) <expression>+)
(let* (<init>+) <expression>+)
(letrec (<init>+) <expression>+)

Let bindings create a new environment and introduce bindings to them. In the first ‘basic’ let each init is evaluated in the parent environment. For a let* each initialiser is evaluated in the child environment sequentially allowing the new bindings to reference previous ones. In the final letrec form each new binding is initialised with some placeholder value before the intialiser expressions are evaluated in the child environment allowing full mutual recursion.

Implementation status

Lexical bindings are implemneted.

Definitions

(define <variable> <expression>?)
(define <formals> <expression>+)

Define statements bind variables to new storage location and assign them a value. Simple define forms without an assign some nominal unknown value. Definitions can be mutually recursive within a lambda, but only up to the first non-definition expression.

Procedure definitions are just lambdas bound to the name that occurs as the first element of the <formals> definition.

Implementation status

Variable definitions are bound and lowered. Function definitions are bound as definitions of lambdas and rely on lambda support for lowering.

Internal deifnitions (that is a define that isn’t in the root) aren’t properly handled. Internal definitions should be mutually recursive. Definitions in internal contexts should only be permitted before the first non-definition expression.

Assignments

(set! <variable> <expression>)

Set expressions assign the result of <expression> to the location that <variable> is currently bound to. If <variable> is unbound then the expression raises an error.

Implementation status

Assignments are bound and lowered.

Quoting

(quote <expression>)
'<expression>
,<expression>

Quote expressions evaluate to the external representation of the expression rather than evaluating the expression directly. For literals there is no difference. For lists this skips application and allows creation of lists directly.

Implementation status

Simple quoted forms are implemented. As well as the standard ’ character for quoting we also support for compatibility with example code in LaTeX docs.

Quasiquote is not supported yet.

Conditionals

(if <cond> <if-true> <if-false>?)
(when <cond> <if-true>+)
(unless <cond> <if-false>+)

An if expression evaluates the <cond>ition followed by one of either <if-true> or <if-false>. This defers the evaluation of the consequent expression until after the variable check. The when and unless forms allow executing multiple expressions in response to true or or false conditions and are shorthands for an if and begin.

(and <expression>*)
(or <expression>*)

Boolean conditional expressions. Both lazily evaluate the given expression returning the result of the last expression that needed to be evaluated to derive the overall truthiness of the expression. An empty and is implicitly truthy, an empty or implicitly falsey.

(cond <clause>+)

Where each <clause> is (<predicate> <expression>+). Evaluates the first <clause>’s body where the <predicate> is truthy. The final predicate may be else, which is always considered truthy.

(case <key> <case>+)

Where <case> is ((<value>+) <expression>+). Evaluates <key> once and then evaluates the body of whichever <case> contains the resulting value in <value>s. The final case may use else in place of the value list to provide a default.

Implementation status

The if conditional special form is implemnted. The and, or, when and unless forms are implemented as builtin macros. The cond and case forms may need macro hygene to be implemented properly.

Sequence

(begin <expression>+)

The begin expression evaluates each inner expression in sequence and returns the result of the final expression.

Implementation status

The begin special form is implemented.