12 Level-0 Defining, Special and Function-call Forms
This section gives the syntax of well-formed expressions and
describes the semantics of the special-forms, functions and syntax
forms of the level-0 language. In the case of level-0 syntax forms,
the description includes a set of expansion rules. However,
these descriptions are not prescriptive of any processor and
a conforming program cannot rely on adherence to these
expansions.
12.1 Simple Expressions
There are two kinds of constants, literal constants and defined
constants. Only the first kind are considered here. A literal
constant is a number, a string, a character, or the empty list. The
result of processing such a literal constant is the constant
itself—that is, it denotes itself.
Examples
() | the empty list |
123 | a fixed precision integer |
#\a | a character |
"abc" | a string |
12.1.2.1 Syntax
Arguments
-
identifier :
-
A symbol naming an immutable top-lexical binding to be
initialized with the value of form.
-
form :
-
The form whose value will be stored in the binding of
identifier.
Remarks
The value of form is stored in the top-lexical binding of identifier.
It is a violation to attempt to modify the binding of a defined
constant.
Remarks
This may be used to denote the abstract boolean value true, but so
may any other value than ().
The current lexical binding of symbol is returned. A symbol can
also name a defined constant—that is, an immutable top-lexical
binding.
12.1.5.1 Syntax
Arguments
-
identifier :
-
A symbol naming a binding containing the value of form.
-
form :
-
The form whose value will be stored in the binding of
identifier.
Remarks
The value of form is stored in the top-lexical binding of identifier.
The binding created by a deflocal form is mutable.
See also
setq.
12.1.6.1 Syntax
Arguments
-
object :
-
the object to be quoted.
Result
The result is object.
Remarks
The result of processing the expression (quote object) is object.
The object can be any object having an external representation .
The special form quote can be abbreviated using apostrophe —
graphic representation ’ — so that (quote a) can be written ’a.
These two notations are used to incorporate literal constants
in programs. It is an error to modify a literal expression
.
Remarks
See quote.
12.2 Functions: creation, definition and application
12.2.1.1 Syntax
Arguments
-
lambda-list :
-
The parameter list of the function conforming to the
syntax 12.2.1.1.
-
form :
-
An expression.
Result
A function with the specified lambda-list and sequence of
forms.
Remarks
The function construction operator is lambda. Access to the lexical
environment of definition is guaranteed. The syntax of lambda-list
is defined in reflambda-syntax-table.
If lambda-list is an identifier, it is bound to a newly allocated list of
the actual parameters. This binding has lexical scope and indefinite
extent. If lambda-list is a simple-list, the arguments are bound to
the corresponding identifier. Otherwise, lambda-list must be a
rest-list. In this case, each identifier preceding the dot is bound to
the corresponding argument and the identifier succeeding the dot
is bound to a newly allocated list whose elements are the
remaining arguments. These bindings have lexical scope and
indefinite extent. It is a violation if the same identifier appears
more than once in a lambda-list. It is an error to modify
rest-list.
12.2.2.1 Syntax
Arguments
-
syntax-operator-name :
-
A symbol naming an immutable top-lexical binding to be
initialized with a function having the specified lambda-list
and body.
-
lambda-list :
-
The parameter list of the function conforming to the
syntax specified under lambda.
-
body :
-
A sequence of forms.
Remarks
The defsyntax form defines a syntax operator named by
syntax-operator-name and stores the definition as the top-lexical
binding of syntax-operator-name . The interpretation of the
lambda-list is as defined for lambda (see 12.2.1.1).
NOTE 1 A syntax operator is automatically exported from the
the module which defines because it cannot be used in the module
which defines it.
See also
lambda.
12.2.3.1 Syntax
Arguments
-
function-name :
-
A symbol naming an immutable top-lexical binding to be
initialized with a function having the specified lambda-list
and body.
-
(setter function-name) :
-
An expression denoting the setter function to correspond
to function-name.
-
lambda-list :
-
The parameter list of the function conforming to the
syntax specified under lambda.
-
body :
-
A sequence of forms.
Remarks
The defun form defines a function named by function-name and
stores the definition (i) as the top-lexical binding of function-name
or (ii) as the setter function of function-name. The interpretation
of the lambda-list is as defined for lambda.
12.2.3.2 Rewrite
Rules
12.2.4.1 Syntax
Arguments
-
operator :
-
This may be a symbol—being either the name of a special
form, or a lexical variable—or a function call, which must
result in an instance of <function>.
An error is signalled (condition class: <invalid-operator>
) if the operator is not a function.
-
operand* :
-
Each operand must be either an identifier, a literal, a
special-form or a function-call-form.
Result
The result is the value of the application of operator to the
evaluation of operand*.
Remarks
The operand expressions are evaluated in order from left
to right. The operator expression may be evaluated at any
time before, during or after the evaluation of the operands.
NOTE 2 The above rule for the evaluation of function calls was
finally agreed upon for this version since it is in line with one strand
of common practice, but it may be revised in a future version.
See also
constant, symbol, quote.
12.2.5 <invalid-operator>
Initialization Options
-
invalid-operator object :
-
The object which was being used as an operator.
-
operand-list list :
-
The operands prepared for the operator.
Remarks
Signalled by function call if the operator is not an instance of
<function>.
12.2.6.1 Syntax
Arguments
-
function :
-
A form which must evaluate to an instance of <function>.
-
form1 ... formn-1 :
-
A sequence of expressions, which will be evaluated
according to the rules given in function-call-form.
-
formn :
-
An expression which must evaluate to a proper list. It is
an error if objn is not a proper list.
Result
The result is the result of calling function with the actual
parameter list created by appending formn to a list of the
arguments form1 through formn-1. An error is signalled (condition
class: <invalid-operator>) if the first argument is not an instance
of <function>.
See also
function-call-form, <invalid-operator>.
12.3 Destructive Operations
An assignment operation modifies the contents of a binding named
by a identifier—that is, a variable.
12.3.1.1 Syntax
Arguments
-
identifier :
-
The identifier whose lexical binding is to be updated.
-
form :
-
An expression whose value is to be stored in the binding
of identifier.
Result
The result is the value of form.
Remarks
The form is evaluated and the result is stored in the closest lexical
binding named by identifier. It is a violation to modify an
immutable binding.
Arguments
-
reader :
-
An expression which must evaluate to an instance of
<function>.
Result
The writer corresponding to reader.
Remarks
A generalized place update facility is provided by setter. Given
reader, setter returns the corresponding update function. If no
such function is known to setter, an error is signalled (condition
class: <no-setter>). Thus (setter car) returns the function to
update the car of a pair. New update functions can be added by
using setter’s update function, which is accessed by the expression
(setter setter). Thus ((setter setter) a-reader a-writer)
installs the function which is the value of a-writer as the writer of
the reader function which is the value of a-reader. All writer
functions in this definition and user-defined writers have the same
immutable status as other standard functions, such that
attempting to redefine such a function, for example ((setter
setter) car a-new-value), signals an error (condition class:
<cannot-update-setter>)
See also
defgeneric, defmethod, defclass, defun.
Initialization Options
-
object object :
-
The object given to setter.
Remarks
Signalled by setter if there is no updater for the given function.
12.3.4 <cannot-update-setter>
Initialization Options
-
accessor object1 :
-
The given accessor object.
-
updater object2 :
-
The given updater object.
Remarks
Signalled by (setter setter) if the updater of the given accessor
is immutable.
See also
setter.
12.4 Conditional Expressions
12.4.1.1 Syntax
Result
Either the value of consequent or alternative depending on the
value of antecedent.
Remarks
The antecedent is evaluated. If the result is t the consequent is
evaluated, otherwise the alternative is evaluated. Both consequent
and alternative must be specified. The result of if is the result of
the evaluation of whichever of consequent or alternative is
chosen.
12.4.2.1 Syntax
Remarks
The cond syntax operator provides a convenient syntax for
collections of if-then-elseif...else expressions.
12.4.2.2 Rewrite Rules
Remarks
This may be used to denote the default clause in cond and ??
forms and has the value t, i.e. it is an alias for t introduced to
improve readability of the cond and ?? forms.
12.4.4.1 Syntax
Result
The antecedent is evaluated and if the result is t the consequent is
evaluated and returned otherwise () is returned.
12.4.4.2 Rewrite Rules
12.4.5.1 Syntax
Result
The antecedent is evaluated and if the result is () the consequent is
evaluated and returned otherwise () is returned.
12.4.5.2 Rewrite Rules
12.4.6.1 Syntax
Remarks
The expansion of an and form leads to the evaluation of the
sequence of forms from left to right. The first form in the sequence
that evaluates to () stops evaluation and none of the forms to its
right will be evaluated—that is to say, it is non-strict. The result of
(and) is t. If none of the forms evaluate to (), the value of the last
form is returned.
12.4.6.2 Rewrite Rules
12.4.7.1 Syntax
Remarks
The expansion of an or form leads to the evaluation of the
sequence of forms from left to right. The value of the first form
that evaluates to t is the result of the or form and none of the
forms to its right will be evaluated—that is to say, it is non-strict.
If none of the forms evaluate to t, the value of the last form is
returned.
12.4.7.2 Rewrite Rules
Note that x does not occur free in any of form2 …formn.
12.5 Variable Binding and Sequences
12.5.1.1 Syntax
Arguments
-
identifier :
-
To be bound to the continuation of the let/cc form.
-
body :
-
A sequence of forms to evaluate.
Result
The result of evaluating the last form in body or the value of the
argument given to the continuation bound to identifier.
Remarks
The identifier is bound to a new location, which is initialized with
the continuation of the let/cc form. This binding is immutable
and has lexical scope and indefinite extent. Each form in
body is evaluated in order in the environment extended by
the above binding. It is an error to call the continuation
outside the dynamic extent of the let/cc form that created it.
The continuation is a function of one argument. Calling the
continuation causes the restoration of the lexical environment and
dynamic environment that existed before entering the let/cc
form.
Examples
An example of the use of let/cc is given in example 1. The
function path-open takes a list of paths, the name of a file
and list of options to pass to open. It tries to open the file
by appending the name to each path in turn. Each time
open fails, it signals a condition that the file was not found
which is trapped by the handler function. That calls the
continuation bound to fail to cause it to try the next path in the
list. When open does find a file, the continuation bound to
succeed is called with the stream as its argument, which is
subsequently returned to the caller of path-open. If the path list
is exhausted, map (section 16.2) terminates and an error
(condition class: ??) is signalled.
(defun path-open (pathlist name . options)
(let/cc succeed
(map
(lambda (path)
(let/cc fail
(with-handler
(lambda (condition resume) (fail ()))
(succeed
(apply open
(format () "~a/~a" path name)
options)))))
pathlist)
(error
(format ()
"Cannot open stream for (~a) ~a"
pathlist name)
<cannot-open-path>)))
See also
block, return-from.
12.5.2.1 Syntax
Remarks
The block expression is used to establish a statically scoped
binding of an escape function. The block identifier is bound
to the continuation of the block. The continuation can be
invoked anywhere within the block by using return-from.
The forms are evaluated in sequence and the value of the
last one is returned as the value of the block form. See also
let/cc.
12.5.2.2 Rewrite Rules
The rewrite for block does not prevent the block being exited
from anywhere in its dynamic extent, since the function bound to
identifier is a first-class item and can be passed as an argument like
other values.
See also
return-from.
12.5.3.1 Syntax
Remarks
In return-from, the identifier names the continuation of the
(lexical) block from which to return. return-from is the
invocation of the continuation of the block named by identifier.
The form is evaluated and the value is returned as the value of the
block named by identifier.
12.5.3.2 Rewrite Rules
See also
block.
12.5.4.1 Syntax
Arguments
-
identifier :
-
A symbol naming a new inner-lexical binding to be
initialized with the function having the lambda-list and
body specified.
-
lambda-list :
-
The parameter list of the function conforming to the
syntax specified below.
-
body :
-
A sequence of forms.
-
letfuns-body :
-
A sequence of forms.
Result
The letfuns operator provides for local mutually recursive
function creation. Each identifier is bound to a new inner-lexical
binding initialized with the function constructed from lambda-list
and body. The scope of the identifiers is the entire letfuns form.
The lambda-list is either a single variable or a list of variables—see
lambda. Each form in letfuns-body is evaluated in order in the
lexical environment extended with the bindings of the identifiers.
The result of evaluating the last form in letfuns-body is returned as
the result of the letfuns form.
12.5.5.1 Syntax
Remarks
The optional identifier denotes that the let form can be called from
within its body. This is an abbreviation for letfuns form in which
identifier is bound to a function whose parameters are the
identifiers of the bindings of the let, whose body is that of the let
and whose initial call passes the values of the initializing form of
the bindings. A binding is specified by either an identifier or a two
element list of an identifier and an initializing form. All the
initializing forms are evaluated in order from left to right in the
current environment and the variables named by the identifiers in
the bindings are bound to new locations holding the results.
Each form in body is evaluated in order in the environment
extended by the above bindings. The result of evaluating
the last form in body is returned as the result of the let
form.
12.5.5.2 Rewrite
Rules
12.5.6.1 Syntax
Remarks
A binding is specified by a two element list of a variable and an
initializing form. The first initializing form is evaluated in the
current environment and the corresponding variable is bound to a
new location containing that result. Subsequent bindings
are processed in turn, evaluating the initializing form in the
environment extended by the previous binding. Each form in body
is evaluated in order in the environment extended by the above
bindings. The result of evaluating the last form is returned as the
result of the let* form.
12.5.6.2 Rewrite
Rules
12.5.7.1 Syntax
Arguments
-
form* :
-
A sequence of forms and in certain circumstances, defining
forms.
Result
The sequence of forms is evaluated from left to right, returning the
value of the last one as the result of the progn form. If the
sequence of forms is empty, progn returns ().
Remarks
If the progn form occurs enclosed only by progn forms and a
defmodule form, then the forms within the progn can be defining
forms, since they appear in the top-lexical environment. It
is a violation for defining forms to appear in inner-lexical
environments.
12.5.8.1 Syntax
Arguments
-
protected-form :
-
A form.
-
after-form* :
-
A sequence of forms.
Result
The value of protected-form.
Remarks
The normal action of unwind-protect is to process protected-form
and then each of after-forms in order, returning the value of
protected-form as the result of unwind-protect. A non-local exit
from the dynamic extent of protected-form, which can be caused by
processing a non-local exit form, will cause each of after-forms to
be processed before control goes to the continuation specified in
the non-local exit form. The after-forms are not protected in any
way by the current unwind-protect. Should any kind of
non-local exit occur during the processing of the after-forms, the
after-forms being processed are not reentered. Instead, control is
transferred to wherever specified by the new non-local exit but the
after-forms of any intervening unwind-protects between the
dynamic extent of the target of control transfer and the current
unwind-protect are evaluated in increasing order of dynamic
extent.
Examples
(progn
(let/cc k1
(letfuns
((loop
(let/cc k2
(unwind-protect (k1 10) (k2 99))
;; continuation bound to k2
(loop))))
(loop)))
;; continuation bound to k1
...)
The code fragment in example 2 illustrates both the use of
unwind-protect and of a difference between the semantics of EU
LISP and some other Lisps. Stepping through the evaluation of this
form: k1 is bound to the continuation of its let/cc form; a
recursive function named loop is constructed, loop is called from
the body of the letfuns form; k2 is bound to the continuation of
its let/cc form; unwind-protect calls k1; the after forms of
unwind-protect are evaluated in order; k2 is called; loop is called;etc.. This program loops indefinitely.
12.6 Quasiquotation Expressions
12.6.1.1 Syntax
Remarks
Quasiquotation is also known as backquoting. A quasiquoted
expression is a convenient way of building a structure. The skeleton
describes the shape and, generally, many of the entries in the
structure but some holes remain to be filled. The quasiquote
syntax operator can be abbreviated by using the glyph called grave
accent (‘) , so that (quasiquote skeleton) can be written
‘skeleton.
Remarks
See quasiquote.
12.6.3.1 Syntax
Remarks
See unquote-splicing.
Remarks
See unquote.
12.6.5.1 Syntax
Remarks
The holes in a quasiquoted expression are identified by unquote
expressions of which there are two kinds—forms whose value is to
be inserted at that location in the structure and forms whose
value is to be spliced into the structure at that location. The
former is indicated by an unquote expression and the latter
by an unquote-splicing expression. In unquote-splicing
the form must result in a proper list. The insertion of the
result of an unquote-splice expression is as if the opening
and closing parentheses of the list are removed and all the
elements of the list are appended in place of the unquote-splice
expression.
The syntax forms unquote and unquote-splicing can be
abbreviated respectively by using the glyph called comma (,)
preceding an expression and by using the diphthong comma
followed by the glyph called commercial at (,@) preceding a form.
Thus, (unquote a) may be written ,a and (unquote-splicing a)
can be written ,@a.
Examples
‘(a ,(list 1 2) b) | → | (a (1 2) b) |
‘(a ,@(list 1 2) b) | → | (a 1 2 b) |
Remarks
See unquote-splicing.
12.7 Summary of Level-0 Defining, Special and Function-call
Forms
This section gives the syntax of the character-set, comments and
all level-0 forms starting with modules. The syntax of data objects
is given in the section pertaining to the class and is summarized in
section 16.20.
| A B C D E F G H I J K L M |
| N O P Q R S T U V W X Y Z |
| a b c d e f g h i j k l m |
| n o p q r s t u v w x y z |
| ; all subsequent characters |
| | up to the end of the line |
12.7.1 Syntax of Level-0 modules
12.7.2 Syntax of Level-0 defining forms
12.7.3 Syntax of Level-0 special forms
12.7.4 Syntax of Level-0 function calls
12.8 Conditions
The defined name of this module is condition.
The condition system was influenced by the Common Lisp error
system [16] and the Standard ML exception mechanism. It is a
simplification of the former and an extension of the latter.
Following standard practice, this text defines the actions
of functions in terms of their normal behaviour. Where an
exceptional behaviour might arise, this has been defined in terms
of a condition. However, not all exceptional situations are
errors. Following Pitman, we use condition to be a kind of
occasion in a program when an exceptional situation has
been signalled. An error is a kind of condition—error and
condition are also used as terms for the objects that represent
exceptional situations. A condition can be signalled continuably
by passing a continuation for the resumption to signal. If a
continuation is not supplied then the condition cannot be
continued.
These two categories are characterized as follows:
- A condition might be signalled when some limit has
been transgressed and some corrective action is needed
before processing can resume. For example, memory zone
exhaustion on attempting to heap-allocate an item can be
corrected by calling the memory management scheme to
recover dead space. However, if no space was recovered a
new kind of condition has arisen. Another example arises
in the use of IEEE floating point arithmetic, where a
condition might be signalled to indicate divergence of an
operation. A condition should be signalled continuably
when there is a strategy for recovery from the condition.
- Alternatively, a condition might be signalled when some
catastrophic situation is recognized, such as the memory
manager being unable to allocate more memory or unable
to recover sufficient memory from that already allocated.
A condition should be signalled non-continuably when
there is no reasonable way to resume processing.
A condition class is defined using defcondition (see § 13.0.1). The
definition of a condition causes the creation of a new class of
condition. A condition is signalled using the function signal,
which has two required arguments and one optional argument: an
instance of a condition, a resume continuation or the empty
list—the latter signifying a non-continuable signal—and a thread.
A condition can be handled using the special form with-handler,
which takes a function—the handler function—and a sequence of
forms to be protected. The initial condition class hierarchy is
shown in table 2.
Table 2: | Condition class hierarchy |