(lambda formals body)- syntax
Syntax: Formals is a formal parameter list as described below, and
body is a body as described by Section 2.6.
Semantics: A lambda expression evaluates to a procedure. The
environment in effect when the lambda expression is evaluated is
remembered as part of the procedure. When the procedure is later
called with some arguments, the environment in which the lambda
expression was evaluated is extended by binding the variables in the
parameter list to fresh locations, and the resulting argument values
are stored in those locations. Then, the forms in the body of the
lambda expression (which may contain definitions and thus represent a
letrec* form, see Section 2.6) are evaluated sequentially in the
extended environment. The results of the last expression in the body
are returned as the results of the procedure call; the last expression
in the body is in tail context.
Formals must have one of the following forms:
(variable1 ...): The procedure takes a fixed number of
arguments; when the procedure is called, the arguments are stored in
the bindings of the corresponding variables.
variable: The procedure takes any number of arguments; when
the procedure is called, the sequence of arguments is converted into
a newly allocated list, and the list is stored in the binding of the
variable.
(variable1 ... variablen . <<variable_(n+1)>>): If a
period . precedes the last variable, then the procedure takes n or
more arguments, where n is the number of parameters before the
period (there must be at least one). The value stored in the binding
of the last variable is a newly allocated list of the arguments left
over after all the other arguments have been matched up against the
other parameters.
It is a syntax violation for a variable to appear more than once
in formals.
Each procedure created as the result of evaluating a lambda
expression receives (conceptually) a fresh location tag, distinct from
the location tags of all existing procedures. Implementations may
avoid creating a new procedure object when evaluating a lambda
expression if they can prove before doing so that the behaviour of the
resulting procedure when called would be the same (returning the same
values and having the same side effects) as an existing procedure, for
all arguments to that procedure. In this case, the lambda expression
will evaluate to that existing procedure, which will retain the same
location tag it was given when created.
(case-lambda case-lambda clause ...)- syntax
Syntax: Each case-lambda clause must be of the form
(formals body)
Formals must be as in a lambda form.
Semantics: A case-lambda expression evaluates to a procedure. This
procedure, when applied, tries to match its arguments to the
case-lambda clauses in order from left to right. The arguments
match a clause if one of the following conditions is fulfilled:
Formals has the form (variable ...) and the number of
arguments is the same as the number of formal parameters in
formals.
Formals has the form (variable1 ...variablen .
variablem) and the number of arguments is at least .
[Editorial note: Markup issue where <<variable_n+1>> does not render correctly ]
Formals has the form variable.
For the leftmost clause matched by the arguments, the variables of the
formals are bound to fresh locations containing the argument
values in the same arrangement as with lambda.
The last expression of a body in a case-lambda expression is in
tail context.
The procedure returned by case-lambda is given a location tag, under
the same conditions as procedures returned by lambda.
Example:
(define foo
(case-lambda
(() 'zero)
((x) (list 'one x))
((x y) (list 'two x y))
((a b c d . e) (list 'four a b c d e))
(rest (list 'rest rest))))
(foo 1 2 3)
⇒(rest (1 2 3))
(foo 1 2 3 4)
⇒(four 1 2 3 4 ())
Todo: R6RS provided a sample implementation in terms of lambda. I
think this is a bad idea because case-lambda is really the primitive
and lambda the derived form. Should we provide one anyway?
(procedure? obj)- procedure
Returns #t if obj is a procedure; otherwise, returns #f.
(procedure? (lambda (x) (* x x)))
⇒#t
(procedure? '(lambda (x) (* x x)))
⇒#f
(apply proc arg1 ... rest-args)- procedure
rest-args must be a list. proc should accept
arguments, where is the number of args plus the length of the
list rest-args.
The apply procedure calls proc with the elements of
the list (append (list arg1 ...) rest-args) as the actual
arguments. If a call to apply occurs in a tail context, the call to
proc is also in a tail context.
Examples:
(define compose
(lambda (f g)
(lambda args
(f (apply g args)))))
((compose sqrt *) 12 75)
⇒30
(values obj ...)- procedure
Delivers all of its arguments to its continuation.
[Editorial note: Reference implementation as in the R7RS? ]
(call-with-values producer consumer)- procedure
producer must be a procedure which accepts zero
arguments. consumer must be a procedure which accepts as many
arguments as the number of values producer returns when applied to
zero arguments.
The call-with-values procedure calls producer with no
arguments and a continuation that, when passed some values, calls the
consumer procedure with those values as arguments. The continuation
for the call to consumer is the continuation of the call to
call-with-values. It is a domain error if the consumer does not
accept as many values as producer returned.
If a call to call-with-values occurs in a tail context, the call to
consumer is also in a tail context.
Examples:
(call-with-values * -)
⇒-1
(define variable expression)- syntax
(define variable)- syntax
(define (procedure spec formals) body)- syntax
(define (procedure spec . formal) body)- syntax
Syntax: Variable is an identifier. Procedure spec is either an
identifier or one of the following:
(procedure spec formals)
(procedure spec . formal)
Formal is a variable. Formals is one of the following:
variable ...
variable1 variable2 ... . variablen
Within the formal and formals, no variable may occur more
than once, including in different procedure specs.
Semantics: Define is a definition form (see
section 4.2) used to create variable
bindings; it may appear anywhere other definitions may appear.
The first form of define evaluates the expression it is given,
binds the identifier named by variable to a new location and
assigns the value of the evaluation to that location. An assertion
violation must be signalled if the expression returns zero values
or more than one value. The continuation of the expression must
not be returned to more than once: implementations should signal an
assertion violation when they detect this has occurred.
The second form of define binds the identifier named by variable
to a new location and assigns an unspecified value to that location.
The third and fourth variants of define are equivalent to a
recursive transformation into a define expression of the first form.
Define in these forms binds the identifier named by the innermost
nested procedure spec to a procedure that may otherwise be
expressed as a number of nested lambda expressions. The formal
or formals on the left-hand side of the define form itself
become the formals of the outermost lambda expression; those of
the procedure spec nested within each subsequent level of nesting
become the next most inner lambda expression formals. The
innermost lambda expression contains the body from the define
form.
Examples: The basic form of define may be used as follows.
The procedure-definition form of define may be used as follows.
(define (step u)
(if (<= 0 u 1) 1 0))
(define ((equal?-proc x) y)
(equal? x y))
(define three? (equal?-proc 3))
Note: The second form of define is allowed by R6RS but the small
language report did not include it. The ability to define higher-order
procedures by nesting list-structured forms on the left-hand side of
define is new in this fascicle, and is not in the small language
report nor in any previous Scheme report. The (scheme base) library
must export the same binding as [Editorial note: whatever large language library
this ends up in ].
(define-values formals expression)- syntax
Syntax: Formals is as for a lambda expression.
Semantics: Define-values is a definition form used to create
variable bindings from an expression whose evaluation may return
multiple values.
The expression is evaluated, and the variables named by the
formals are bound to the return values in the same way that the
formals in a lambda expression are matched to the arguments in a
procedure call. If the evaluation of the expression returns a
number of values which cannot be reconciled with the formals, an
assertion violation is signalled.
(define-alias identifier1 identifier2)- syntax
Define-alias is a definition form which causes identifier1 to
refer to the same binding as identifier2. Uses of
identifier1 will, throughout the region of the definition, be the
same as uses of identifier2 in the sense of free-identifier=?,
but not in the sense of bound-identifier=? (see [Editorial note: cross-reference to
macrological fascicle ]). In particular, shadowing of
identifier1 or identifier2 within regions nested inside the
region where the define-alias has effect will locally cancel the
effect of define-alias.
Identifier2 may refer to any kind of binding, including a
variable, syntax keyword, or a pattern variable. Because
identifier1 receives the same binding as identifier2, its
binding has the same binding type as identifier2. If
identifier2 is a variable or pattern variable, it is bound to the
same location as identifier1. If identifier2 is a syntax
keyword, use of identifier2 within the region of the definition
invokes the same trtransformer on the macro use as a use of
identifier1 would. It is a syntax violation if the
identifier2 is not already bound.
Example:
(define foo 3)
(define-alias bar foo)
(let bindings body)- syntax
(let name bindings body)- syntax
Syntax: Bindings has the form
((variable1 init1) ...)
where each init is an expression. Any variable must not appear
more than once in the variables. Name, if present, is an
identifier.
Semantics: Let is a binding expression.
In the first form of, evaluation of a let expression proceeds as
follows. The init expressions of the bindings are evaluated in
an unspecified order in the current environment, the variables are
bound to fresh locations holding the results, and the result of
evaluating the body in this extended environment is returned. The
body is evaluated in tail context if the let expression is in a
tail context.
In the second form, commonly referred to as ‘named let’, the
name is additionally bound as a variable within the evaluation of
the body to a procedure whose parameters are the bound variables
and whose body is body. Thus the execution of body may be
repeated by invoking the procedure named by variable.
Implementation:
(define-syntax let
(syntax-rules ()
((_ ((var init) ...) body_0 body_1 ...)
((lambda (var ...) body_0 body_1 ...) init ...))
((_ name ((var init) ...) body_0 body_1 ...)
((rec (name var ...) body_0 body_1 ...) init ...))))
(let* bindings body)- syntax
Syntax: Bindings is as for let, except that the same variable
can be named multiple times.
Semantics: The let* form is similar to let, but the inits are
evaluated and bindings created sequentially from left to right, with
the region of each binding including the bindings to its right as well
as body. Thus the second init is evaluated in an environment
in which the first binding is visible and initialized, and so on.
(let-values mv bindings body)- syntax
Syntax: Mv bindings has the form
((formals1 init1) ...)
where each formals is as for a define-values definition and each
init is an expression. Any variable must not appear more than once
in the set of all formals.
Semantics: The init expressions of the mv bindings are
evaluated in an unspecified order as in let; and the variables
occurring in the formals are bound to fresh locations containing
the values returned by the inits, where the formals are
matched to the return values in the same way that the formals in a
lambda expression are matched to the arguments in a procedure call.
Then, the body is evaluated in the extended environment, and the
values of the last expression of body are returned. Each binding
of a variable has body as its region. If the formals do not
match, an assertion violation is signalled.
(let*-values mv bindings body)- syntax
Syntax: Mv bindings is as for let-values, except that a variable
which appears in one formals can appear again in a subsequent
formals.
(letrec bindings body)- syntax
Syntax: Bindings is as for let.
Semantics: The variables are bound to fresh locations, the
inits are evaluated in the resulting environment (in some
unspecified order), each variable is assigned to the result of the
corresponding init, the body is evaluated in the resulting
environment, and the values of the last expression in body are
returned. Each binding of a variable has the entire letrec
expression as its region, making it possible to define mutually
recursive procedures.
It must be possible to evaluate each init without assigning or
referring to the value of any variable. Implementations should
signal an assertion violation if they detect that the value of a
variable is accessed or assigned during the evaluation of any
init (within the limitations of one particular evaluation order
and order of evaluating the init expressions). In the most common
uses of letrec, all the inits are lambda expressions and the
restriction is satisfied automatically.
The continuation of each init should not be invoked more than
once. Implementations should detect this and signal an assertion
violation.
The body is evaluated in tail context if the letrec expression
as a whole is in tail context.
(letrec* bindings body)- syntax
Syntax: Bindings is as for let.
Semantics: The variables are bound to fresh locations, each
variable is assigned in left-to-right order to the result of
evaluating the corresponding init (interleaving evaluations and
assignments), the body is evaluated in the resulting environment,
and the values of the last expression in body are returned.
Despite the left-to-right evaluation and assignment order, each
binding of a variable has the entire letrec* expression as its
region, making it possible to define mutually recursive procedures.
It must be possible to evaluate each init without accessing or
assigning the value of the corresponding variable or of any
variable whose binding follows it in bindings. Implementations
should signal an assertion violation if they detect that this
restriction is violated.
Note: Letrec* differs from letrec in that the order of evaluation
of init expressions is strictly defined as left-to-right, and the
values of previously-bound variables may be accessed during the
evaluation of init. While implementations which do not follow this
report’s recommendation to signal an assertion violation upon use of
previously-bound variables in letrec are conforming, programmers
cannot rely on this behaviour in portable code.
The difference between letrec and letrec* is not quite analogous
to the difference between let and let*, because in let* (but not
in let) the same variable can be named multiple times in different
binding clauses, which is not allowed in letrec nor in letrec*.
The continuation of each init should not be invoked
more than once. Implementations should detect this and signal an
assertion violation.
The body is evaluated in tail context if the letrec* expression
as a whole is in tail context.
(letrec-values mv bindings body)- syntax
Syntax: Mv bindings is as for let-values.
Semantics: All the variables in the formals are bound to fresh
locations, the inits are evaluated in the resulting environment
(in some unspecified order), and each variable of the formals is
assigned to a corresponding value or list of values from the result of
those formals init, the body is evaluated in the
resulting environment, and the values of the last expression in
body are returned.
The same restrictions on accessing or assigning the value of a
variable named by the formals during the evaluation of any
init expression, and on returning to the continuation of an
init expression, which apply to letrec apply also to
letrec-values. Implementation should signal an assertion violation
if they detect that these restrictions are violated.
The body is evaluated in tail context if the letrec-values
expression as a whole is in tail context.
(letrec*-values mv bindings body)- syntax
Syntax: Mv bindings is as for let-values.
Semantics: All the variables in the formals are bound to fresh
locations, each variable of the formals is assigned in
left-to-right order to a corresponding value or list of values from
the result of evaluating its formals init (interleaving
evaluations and assignments), the body is evaluated in the
resulting environment, and the values of the last expression in
body are returned.
The same restrictions on the evaluation of any init expression
referring to variable named in the corresponding formals or in any
formals to the right of it, and on returning to the continuation
of an init expression, which apply to letrec* apply also to
letrec*-values. Implementation should signal an assertion violation
if they detect that these restrictions are violated.
The body is evaluated in tail context if the letrec*-values
expression as a whole is in tail context.
(rec variable expression)- syntax
(rec (variable formals) body)- syntax
(rec (variable . formal) body)- syntax
Syntax: Formal and formals are as for define.
Semantics: Rec is a form for creating self-recursive expressions and
procedures.
In the first form of rec, the expression is evaluated in an
environment in which the variable is bound to a location which
will eventually contain the result of evaluating that expression. If
evaluation of the expression results in an attempt to access or
assign the value of the variable, or if the continuation of the
evaluation of the expression is returned to more than once, an
assertion violation should be signalled. This form of rec can be
used to create self-recursive procedures or lazy data structures with
delay, but not cyclical values.
The second and third forms of rec evaluate to a procedure whose
environment contains a binding for the variable which refers to
the procedure itself. The formals or formal give the arguments
to the resulting procedure in the same way as in the left-hand side of
define.
Examples:
(car (rec s (cons 1 (delay s))))
⇒1
(car (force (cdr (rec s (cons 1 (delay s))))))
⇒1
(car (force (cdr (force (cdr (rec s (cons 1 (delay s))))))))
⇒1
Implementation:
(define-syntax rec
(syntax-rules ()
((_ (name . formals) body_0 body_1 ...)
(letrec ((name (lambda formals
body_0 body_1 ...)))
name))
((_ name expr)
(letrec ((name expr))
name))))
Note: This form is a combination of two historical forms, rec and
named-lambda, which appeared in the RRRS but have not been included
in any Scheme report since. Only the first form of rec in this
report is compatible with the form which had the name rec in the
RRRS; the other two forms correspond to named-lambda.
(set! variable expression)- syntax
Syntax: Variable is a variable which is already bound to some
value in some region enclosing the set! expression or at the top
level. If variable is not bound, it is a violation of type
&undefined. Implementations should report and detect this violation
before evaluation begins in the same contexts in which they should
detect other references to unbound variables (see 3.1).
Note: When the identifier on the left hand side of a set! expression
is not a binding for a variable but for a syntax keyword, the set!
expression is a macro use and its semantics are determined by the
transformer associated with the syntax keyword, not by this entry.
Semantics: The expression is evaluated, and the resulting value is
stored in the location to which the variable is bound. An
unspecified value is returned.
(begin definition or expression ...)- syntax
(begin expression1 expression2 ...)- syntax
When begin is invoked within a body, library body, or
program body, it has the first form, with the effect of splicing
the definition or expression forms contained therein into the
surrounding context, such that any definitions have effect for the
whole of the corresponding body.
Todo: Define what begin does at the REPL (whether it locally causes
R6RS top-level body semantics within itself or not). Probably in the
fascicle on libraries which will define eval.
Rationale: The first form of begin is commonly used in the output of
macros [Editorial note: cross-reference ] which need to generate multiple
definitions and splice them into the context in which they are
expanded. It is also used by macros which generate multiple
expressions, some of which are side-effectual, which may be used in
either a definition or an expression context.
When begin is used in a context where definitions are
not allowed, it has the second form, which is an ordinary expression.
The expressions are evaluated sequentially from left to right, and
the values of the last expression are returned. The last
expression is in tail context if the begin expression as a whole
is in tail context. The continuations of the all expressions except
the last one accept any number of values and discard them. This
expression type is used to sequence side effects such as assignments
or input and output.
Note: There is an additional form of begin used in define-library
declarations [Editorial note: cross-reference to bibliothecarial fascicle ].
Examples:
⇒syntax violation [Editorial note: allow extension which permits this? ]
(if test consequent alternative)- syntax
(if test consequent)- syntax
Syntax: Test, consequent, and alternative must be
expressions.
Semantics: An if expression is evaluated as follows: first, test
is evaluated. If it yields a true value (see [Editorial note: cross reference to
booleans in the valued fascicle ]), then
consequent is evaluated and its values are returned. Otherwise
alternate is evaluated and its values are returned. If test
yields #f and no alternate is specified, then the result of the
expression is unspecified.
The consequent and alternate expressions are in tail context
if the if expression itself is.
Syntax: The tests are expressions.
Semantics: If there are no tests, #t is returned. Otherwise, the
test expressions are evaluated from left to right until a test
returns #f or the last test is reached. In the former case, the
and expression returns #f without evaluating the remaining
expressions. In the latter case, the last expression is evaluated and
its values are returned.
The last test expression is in tail context if the and
expression itself is.
Examples:
(and (= 2 2) (> 2 1))
⇒#t
(and (= 2 2) (< 2 1)) => #f
(and 1 2 'c '(f g)) => (f g)
(and) => #t
Implementation:
(define-syntax and
(syntax-rules ()
((and) #t)
((and test) test)
((and test1 test2 ...)
(if test1 (and test2 ...) #f))))
Syntax: The tests are expressions.
Semantics: If there are no tests, #f is returned. Otherwise, the
<test> expressions are evaluated from left to right until a test
returns a true value, or the last test is reached. In the former
case, the or expression returns that value without evaluating the
remaining expressions. In the latter case, the last expression is
evaluated and its values are returned.
The last test expression is in tail context if the or expression
itself is.
Examples:
(or (= 2 2) (> 2 1))
⇒#t
(or (= 2 2) (< 2 1)) => #t
(or #f #f #f) => #f
(or '(b c) (/ 3 0)) => (b c)
Implementation:
(define-syntax or
(syntax-rules ()
((or) #f)
((or test) test)
((or test1 test2 ...)
(let ((x test1))
(if x x (or test2 ...))))))
(cond cond clause ...)- syntax
=>- auxiliary syntax
else- auxiliary syntax
Syntax: Each cond clause has one of the forms
(test)
(test body)
(test => expression)
(generator guard => expression)
The last cond clause may additionally have the form
(else body)
The test, generator, and guards are all expressions.
Note: The syntax of the second, third, and fourth cond clause
types is not ambiguous because the auxiliary syntax keyword => is
not a valid expression nor definition on its own.
Semantics: A cond expression is evaluated by checking the cond
clauses in order from left to right until the condition required by
one of them is satisfied; then that clause is chosen to generate the
result of evaluating the cond expression, which is returned. The
condition required by each cond clause, and how it generates the
result, is determined by the syntax of each clause:
For clauses of the form (test), the condition for the clause
is satisfied if the evaluating the test expression yields a true
value. The result is the value that was returned by the evaluation
of the test expression.
For clauses of the form (test body), the condition for the
clause is satisfied if evaluating the test expression yields a
true value. The result is generated by evaluating the body. The
body is in tail context if the cond expression as a whole is
in tail context.
For clauses of the form (test => expression), the
condition for the clause is satisfied if evaluating the test
expression yields a true value. The result is generated by first
evaluating the expression. This evaluation must yield a
procedure of one argument. This procedure is called with the result
of the prior evaluation of the test expression to give the
result for the clause. The procedure is called in tail context if
the cond expression is in tail context.
For clauses of the form (generator guard =>
expression), the guard expression must evaluate to a
procedure. The condition for the clause is satisfied if the result
of calling this procedure with the values yielded by evaluating the
generator expression is a true value. The result is generated by
first evaluating the expression. This evaluation must yield a
procedure which takes as many arguments as there were values
resulting from the prior evaluation of the generator expression.
This procedure is then called with those values as arguments to give
the result for the clause. The procedure is called in tail context
if the cond expression is in tail context.
If the final clause is of the form (else body), its condition
is always satisfied. The result is generated by evaluating the
body. The body is in tail context if the cond expression
as a whole is in tail context.
If none of the clauses have their conditions satisfied, the evaluation
of the cond expression returns an unspecified value.
Implementation:
(define-syntax cond
(syntax-rules (else =>)
((_) (if #f #f))
((_ (else body_0 body_1 ...))
(let () body_0 body_1 ...))
((_ (test => proc) clause ...)
(let ((val test))
(if val (proc val) (cond clause ...))))
((_ (generator guard => proc) clause ...)
(let-values ((vals generator))
(if (apply guard vals)
(apply proc vals)
(cond clause ...))))
((_ (test) clause ...)
(let ((val test))
(if val val (cond clause ...))))
((_ (test body_0 body_1 ...) clause ...)
(if test (let () body_0 body_1 ...) (cond clause ...)))))
Note: The clause form (generator guard => expression) is
new in this fascicle, and is not in the small language report nor in
any previous version of the Scheme report. Previous versions of the
Scheme report only allowed expressions, and not definitions, in cond
clauses of the second form and of the else form. The (scheme base)
library must export the same binding as [Editorial note: whatever large language
library this ends up in ].
Issue: In previous Scheme reports, (cond) was not a syntactically
valid expression. It has been made one because it may be easier to
write correct macros which expand into uses of cond when zero
clauses are allowed, especially if the entire cond expression is
being used only for side-effects in any case. This use of cond will
always return an unspecified value. A similar change has been made to
case. The Working Group is especially keen to hear feedback on this
change.
(when test body)- syntax
(unless test body)- syntax
Syntax: Test is an expression.
Semantics: A when or unless expression is evaluated by first
evaluating the test expression. If test evaluates to a true
value in a when expression, or a false value in an unless
expression, the expressions are evaluated in order from left to
right. The final expression is in tail context if the when or
unless form itself is in tail context. Unspecified values are
returned.
Implementation:
(define-syntax when
(syntax-rules ()
((_ test body_0 body_1 ...)
(if test (let () body_0 body_1 ...)))))
(define-syntax unless
(syntax-rules ()
((_ test body_0 body_1 ...)
(if (not test) (let () body_0 body_1 ...)))))
Note: Neither the R6RS nor the small language report allowed
definitions inside of a when or unless, only expressions. R6RS
specified that if the expressions were evaluated, the result of
evaluating the when or unless expression would the result of
evaluating the final expression. The small language report relaxed
this to make the result of when and unless undefined in all cases,
since it could not be depended on in any circumstance.
(case key case clause ...)- syntax
=>- auxiliary syntax
else- auxiliary syntax
Syntax: Key is an expression. Each case clause has one of the
forms
((datum1 ...) body)
((datum1 ...) => expression)
The last case clause may additionally have the form
(else body)
Semantics: A case expression is evaluated by first evaluating the
key expression to produce a single value, called the key. The
case clauses are checked in order from left to right until one is
found which contains a datum whose value as a literal is the same,
in the sense of the eqv? procedure, as the key.
If that clause has the first form listed above, the body is
evaluated and its result returned. The body is in tail context if the
case expression is in tail context.
If the clause has the second form listed above, its expression is
evaluated to produce a procedure of one argument. This procedure is
called with a value which is eqv? to the key as its argument and the
result of this procedure call is returned. The procedure is called in
tail context if the case expression is in tail context.
If no other clause contains a suitable datum for the key and the last
clause has the form (else body), the body is evaluated and
its result returned. The body is evaluated is in tail context if the
case expression is in tail context.
If no clause contains a suitable datum for the key and there is no
clause beginning with the else keyword, unspecified values are
returned.
Note: Because of the use of eqv? to compare the key with the datums
in case clauses, only booleans, identifiers, numbers, characters, and
the empty list can sensibly be used as datums in clauses, as the
semantics of eqv? for these types does not depend on their location
in the store, which is unspecified for literal datums of other types.
Note: Previous versions of the Scheme report only allowed expressions,
and not definitions, in case clauses of the first form and of the
else form.
Issue: In previous Scheme reports, (case key) was not a
syntactically valid expression. It has been made one because it may be
easier to write correct macros which expand into uses of case when
zero clauses are allowed, especially if the entire case expression
is being used only for side-effects in any case. This use of case
will always return an unspecified value. A similar change has been
made to cond. The Working Group is especially keen to hear feedback
on this change.
(do ((variable1 init1 <<step_1>) ...)
(test expression ...)
command ...)- syntax
Syntax: The inits, steps, tests, and commands are
expressions. The variables are distinct identifiers.
Semantics: The do expression is an iteration construct. It specifies
a set of variables to be bound, how they are to be initialized at the
start, and how they are to be updated on each iteration.
A do expression is evaluated as follows: The init expressions are
evaluated (in some unspecified order), the variables are bound to
fresh locations, the results of the init expressions are stored in
the bindings of the variables, and then the iteration phase begins.
Each iteration begins by evaluating test; if the result is a false
value, then the commands are evaluated in order for effect, the
step expressions are evaluated in some unspecified order, the
variables are bound to fresh locations holding the results, and
the next iteration begins.
If test evaluates to a true value, the expressions are
evaluated from left to right and the values of the last expression
are returned. The last expression is in tail context if the do
expression is in tail context. If no expressions are present, then
the do expression returns unspecified values.
The region of the binding of a variable consists of the entire
do expression except for the inits.
A step may be omitted, in which case the effect is the same as if
(variable init variable) had been written instead of
(variable init).
If a do expression appears in a tail context, the expressions
are a tail sequence in the sense of [Editorial note: todo: definition of tail sequences ], i.e., the last
expression is also in a tail context.
Implementation: This definition of do uses a trick to
expand the variable clauses.
(define-syntax do
(syntax-rules ()
((_ ((var init . maybe-step) ...)
(test expr ...)
command ...)
(let-syntax
((do-step
(syntax-rules ()
((_ implicit-step) implicit-step)
((_ _ step) step))))
(let loop ((var init) ...)
(if test
(begin
;; avoid an empty `begin' expression:
(if #f #f)
expr ...)
(begin
command ...
(loop (do-step var . maybe-step) ...))))))))
(eqv? obj1 obj2)- procedure
The eqv? procedure defines a useful equivalence relation on objects.
Briefly, it returns #t if obj1 and obj2 should normally be
regarded as the same object and #f otherwise. This relation is left
slightly open to interpretation, but the following partial
specification of eqv? must hold for all implementations.
If obj1 and obj2 are of distinct disjoint types (see [Editorial note: cross
reference to the valued fascicle on types ]), eqv? always returns #f. Otherwise, eqv? behaves according
to the common disjoint type of obj1 and obj2:
Procedure: eqv? returns #t if the two procedures have the same
location tag. It may also return #t if the implementation can
prove that the two procedures would behave the same for all
arguments, even if they have different location tags. Otherwise, it
returns #f. Note that implementations are not required to make any
particular effort to prove that two procedures have equivalent
behavior.
The eq? predicate is similar to eqv? except that in some cases it
is capable of discerning distinctions finer than those detectable by
eqv?. It must always return #f when eqv? also would, but may
return #f in some cases where eqv? would return #t.
On procedures, the eq? predicate returns #t if the procedures have
the same location tag and #f otherwise.
(equal? obj1 obj2)- procedure
The equal? predicate is a coarser equivalence predicate than eqv?
or eq?. Like those procedures, it returns #f if its arguments are
of distinct disjoint types. Otherwise, it returns #t if and only if
the (possibly infinite) unfoldings of its arguments into regular trees
are the same (in the sense of equal?) as ordered trees.
On procedures, the equal? predicate behaves the same as eqv?.