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


12.1.1 constant
syntax


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 defconstant
defining operator


12.1.2.1 Syntax

defconstant-form: <object>
( defconstant constant-name form )
constant-name:
identifier
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.


12.1.3 t <symbol>
constant


Remarks

This may be used to denote the abstract boolean value true, but so may any other value than ().


12.1.4 symbol
syntax


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 deflocal
defining operator


12.1.5.1 Syntax

deflocal-form: <object>
( deflocal local-name form )
local-name:
identifier
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 quote
special operator


12.1.6.1 Syntax

quote-form: object
( quote object )
object
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 .


12.1.7
syntax


Remarks

See quote.

12.2 Functions: creation, definition and application


12.2.1 lambda
special operator


12.2.1.1 Syntax

lambda-form: <function>
( lambda lambda-list body )
lambda-list:
identifier
simple-list
rest-list
simple-list:
( identifier* )
rest-list:
( identifier* . identifier )
body:
form*
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 defsyntax
defining operator


12.2.2.1 Syntax

defsyntax-form: <function>
( defsyntax syntax-operator-name lambda-list body )
syntax-operator-name:
identifier
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 defun
defining operator


12.2.3.1 Syntax

defun-form: <function>
simple-defun
setter-defun
simple-defun:
( defun function-name lambda-list
body )
setter-defun:
( defun ( setter function-name ) lambda-list
body )
function-name:
identifier
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 function call
syntax


12.2.4.1 Syntax

function-call-form: <object>
( operator operand* )
operator:
identifier
operand:
identifier
literal
special-form
function-call-form
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>
<general-condition>  condition


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 apply
function


12.2.6.1 Syntax

apply-form: <object>
( apply function body )
function:
level-0-form
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 setq
special operator


12.3.1.1 Syntax

setq-form: <object>
( setq identifier form )
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.


12.3.2 setter
function


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.


12.3.3 <no-setter>
<general-condition>  condition


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>
<general-condition>  condition


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 if
special operator


12.4.1.1 Syntax

if-form: <object>
( if antecedent
consequent
alternative )
antecedent:
form
consequent:
form
alternative:
form
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 cond
special operator


12.4.2.1 Syntax

cond-form: <object>
( cond
{( antecedent consequent* )}* )
Remarks

The cond syntax operator provides a convenient syntax for collections of if-then-elseif...else expressions.

12.4.2.2 Rewrite Rules
(cond) ()
(cond (antecedent)
…) (or antecedent (cond …))


12.4.3 else <symbol>
constant


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 when
special operator


12.4.4.1 Syntax

when-form: <object>
( when antecedent
consequent )
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 unless
special operator


12.4.5.1 Syntax

unless-form: <object>
( unless antecedent
consequent )
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 and
special operator


12.4.6.1 Syntax

and-form: <object>
( and consequent* )
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
(and) t
(and form) form
(and form1 form2 …)
(if form1
(and form2 …)
())


12.4.7 or
special operator


12.4.7.1 Syntax

or-form: <object>
( or form* )
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
(or) ()
(or form) form
(or form1 form2 …)
(let ((x form1))
(if x
x
(or form2 …)))

Note that x does not occur free in any of form2formn.

12.5 Variable Binding and Sequences


12.5.1 let/cc
special operator


12.5.1.1 Syntax

let/cc-form: <object>
( let/cc identifier body )
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.

Example 1: using let/cc
(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 block
special operator


12.5.2.1 Syntax

block-form: <object>
( block identifier body )
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
(block identifier)()
(block identifier (let/cc identifier
body) body)

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 return-from
special operator


12.5.3.1 Syntax

return-from-form: <object>
( return-from identifier formopt )
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
(return-from identifier) (identifier ())
(identifier form)
See also

block.


12.5.4 letfuns
special operator


12.5.4.1 Syntax

letfuns-form: <object>
( letfuns
( function-definition* )
letfuns-body )
function-definition:
( identifier lambda-list body )
letfuns-body:
form*
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 let
special operator


12.5.5.1 Syntax

let-form: <object>
( let identifieropt ( binding* )
body )
binding:
variable
( variable form )
variable:
identifier var:
variable
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
(let () body) (progn body)
(let ((var1 form1)
(var2 form2)
var3
…)
body)
((lambda (var1 var2 var3 …)
body)
form1 form2 () …)
(let var0
((var1 form1)
var2
…)
body)
(letfuns
((var0 (var1 var2 …)
body))
(var0 form1 () …))


12.5.6 let*
special operator


12.5.6.1 Syntax

let-star-form: <object>
( let* ( binding* )
body )
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
(let* () body) (progn body)
(let* ((var1 form1)
(var2 form2)
var3
…)
body)
(let ((var1 form1))
(let* ((var2 form2)
var3
…)
body))


12.5.7 progn
special operator


12.5.7.1 Syntax

progn-form: <object>
( progn body )
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 unwind-protect
special operator


12.5.8.1 Syntax

unwind-protect-form: <object>
(unwind-protect protected-form
after-form* )
protected-form:
form
after-form:
form
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


Example 2: Interaction of unwind-protect with non-local exits
(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 quasiquote
special operator


12.6.1.1 Syntax

quasiquote-form: <object>
( quasiquote skeleton )
skeleton
skeleton:
form
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.


12.6.2
syntax


Remarks

See quasiquote.


12.6.3 unquote
special operator


12.6.3.1 Syntax

unquote-form: <object>
( unquote form )
,form
Remarks

See unquote-splicing.


12.6.4 ,
syntax


Remarks

See unquote.


12.6.5 unquote-splicing
special operator


12.6.5.1 Syntax

unquote-splicing-form: <object>
( unquote-splicing form )
,@form
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)


12.6.6 ,@
syntax


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.

decimal-digit: one of
0 1 2 3 4 5 6 7 8 9
upper-letter: one of
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
lower-letter: one of
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
letter:
upper-letter
lower-letter
normal-other-character: one of
* / < = > + .
other-character:
normal-other-character-
special-character: one of
; ’ , \ " # ( ) ‘ | @
level-0-character:
decimal-digit
letter
other-character
special-character
whitespace:
space
newline
line-feed
return
tab
vertical-tab
form-feed
comment:
; all subsequent characters
up to the end of the line
#; whitespace* object

12.7.1 Syntax of Level-0 modules
defmodule-0-form:
( defmodule module-name
module-directives
level-0-module-form* )
module-name:
identifier
module-directives:
( module-directive* )
module-directive:
export ( identifier* )
expose ( module-descriptor* )
import ( module-descriptor* )
syntax ( module-descriptor* )
level-0-module-form:
( export identifier* )
level-0-form
defining-0-form
( progn level-0-module-form* )
module-descriptor:
module-name
module-filter
module-filter:
( except ( identifier* ) module-descriptor )
( only ( identifier* ) module-descriptor )
( rename ( rename-pair* ) module-descriptor )
rename-pair:
( identifier identifier )
level-0-form:
identifier
literal
special-0-form
function-call-form
form:
level-0-form
special-form:
special-0-form

12.7.2 Syntax of Level-0 defining forms
defining-0-form:
defclass-form
defcondition-form
defconstant-form
deflocal-form
defgeneric-form
defsyntax-form
defun-form
defclass-form:
( defclass class-name superclass-name
( slot* ) class-option* )
class-name:
identifier
superclass-name:
identifier
slot:
slot-name
( slot-name slot-option* )
slot-name:
identifier
slot-option:
keyword: identifier
default: level-0-form
reader: identifier
writer: identifier
accessor: identifier
required?: boolean
class-option:
keywords: ( identifier* )
constructor: constructor-specification
predicate: identifier
abstract?: boolean
constructor-specification:
( identifier identifier* )
initlist:
{identifier object}*
defgeneric-form:
( defgeneric gf-name gf-lambda-list
level-0-init-option )
gf-name:
identifier
gf-lambda-list:
specialized-lambda-list
level-0-init-option:
method method-description
method-description:
( specialized-lambda-list form* )
specialized-lambda-list:
( specialized-parameter+ {. identifier} opt )
specialized-parameter:
( identifier class-name )
identifier
defmethod-form:
( defmethod gf-locator
specialized-lambda-list
body )
gf-locator:
identifier
( setter identifier )
( converter identifier )
defconstant-form: <object>
( defconstant constant-name form )
constant-name:
identifier
deflocal-form: <object>
( deflocal local-name form )
local-name:
identifier
defsyntax-form: <function>
( defsyntax syntax-operator-name lambda-list body )
syntax-operator-name:
identifier
defun-form: <function>
simple-defun
setter-defun
simple-defun:
( defun function-name lambda-list
body )
setter-defun:
( defun ( setter function-name ) lambda-list
body )
function-name:
identifier

12.7.3 Syntax of Level-0 special forms
special-0-form:
defmethod-form
generic-lambda-form
quote-form
lambda-form
setq-form
if-form
let/cc-form
letfuns-form
progn-form
unwind-protect-form
quasiquote-form
unquote-form
unquote-splicing-form
call-next-handler-form
with-handler-form
cond-form
and-form
or-form
block-form
return-from-form
let-form
let-star-form
with-input-file-form
with-output-file-form
with-source-form
with-sink-form
generic-lambda-form:
( generic-lambda gf-lambda-list
level-0-init-option* )
lambda-form: <function>
( lambda lambda-list body )
lambda-list:
identifier
simple-list
rest-list
simple-list:
( identifier* )
rest-list:
( identifier* . identifier )
body:
form*
quote-form: object
( quote object )
object
setq-form: <object>
( setq identifier form )
if-form: <object>
( if antecedent
consequent
alternative )
antecedent:
form
consequent:
form
alternative:
form
cond-form: <object>
( cond
{( antecedent consequent* )}* )
when-form: <object>
( when antecedent
consequent )
unless-form: <object>
( unless antecedent
consequent )
and-form: <object>
( and consequent* )
or-form: <object>
( or form* )
let/cc-form: <object>
( let/cc identifier body )
letfuns-form: <object>
( letfuns
( function-definition* )
letfuns-body )
function-definition:
( identifier lambda-list body )
letfuns-body:
form*
progn-form: <object>
( progn body )
unwind-protect-form: <object>
(unwind-protect protected-form
after-form* )
protected-form:
form
after-form:
form
apply-form: <object>
( apply function body )
function:
level-0-form
block-form: <object>
( block identifier body )
return-from-form: <object>
( return-from identifier formopt )
let-form: <object>
( let identifieropt ( binding* )
body )
binding:
variable
( variable form )
variable:
identifier var:
variable
let-star-form: <object>
( let* ( binding* )
body )
quasiquote-form: <object>
( quasiquote skeleton )
skeleton
skeleton:
form
unquote-form: <object>
( unquote form )
,form
unquote-splicing-form: <object>
( unquote-splicing form )
,@form

12.7.4 Syntax of Level-0 function calls
function-call-form: <object>
( operator operand* )
operator:
identifier
operand:
identifier
literal
special-form
function-call-form

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:

  1. 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.
  2. 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
<condition>
<general-condition>
<invalid-operator>
<cannot-update-setter>
<no-setter>
<environment-condition>
<arithmetic-condition>
<division-by-zero>
<conversion-condition>
<no-converter>
??
<end-of-stream>
<read-error>
<thread-condition>
<thread-already-started>
<wrong-thread-continuation>
<wrong-condition-class>
??
<no-next-method>
<generic-function-condition>
<non-congruent-lambda-lists>
<incompatible-method-domain>
<no-applicable-method>
<method-domain-clash>