Documente Academic
Documente Profesional
Documente Cultură
SUMMARY
The report gives a defining description of the programming language Scheme. Scheme is a statically scoped and properly
tail-recursive dialect of the Lisp programming language invented by Guy Lewis Steele Jr. and Gerald Jay Sussman. It was
designed to have an exceptionally clear and simple semantics and few different ways to form expressions. A wide variety
of programming paradigms, including imperative, functional, and message passing styles, find convenient expression in
Scheme.
The introduction offers a brief history of the language and of the report. It also gives a short introduction to the basic
concepts of the language.
Chapter 2 explains Scheme’s number types. Chapter 3 defines the read syntax of Scheme programs. Chapter 4 presents
the fundamental semantic ideas of the language. Chapter 5 defines notational conventions used in the rest of the report.
Chapters 6 and 7 describe libraries and scripts, the basic organizational units of Scheme programs. Chapter 8 explains
the expansion process for Scheme code.
Chapter 9 explains the Scheme base library which contains the fundamental forms useful to programmers.
The next set of chapters describe libraries that provide specific functionality: Unicode semantics for characters and
strings, binary data, list utility procedures, a record system, exceptions and conditions, I/O, specialized libraries for
dealing with numbers and arithmetic, the syntax-case facility for writing arbitrary macros, hash tables, enumerations,
and various miscellaneous libraries.
Chapter 21 describes the composite library containing most of the forms described in this report. Chapter 22 describes the
eval facility for evaluating Scheme expressions represented as data. Chapter 23 describes the operations for mutating
pairs. Chapter 24 describes a library with some procedures from the previous version of this report for backwards
compatibility.
Appendix A provides a formal semantics for a core of Scheme. Appendix B contains definitions for some of the derived
forms described in the report.
The report concludes with a list of references and an alphabetic index.
*** DRAFT***
This is a preliminary draft. It is intended to reflect the decisions taken by the editors’ comittee, but contains many
mistakes, ambiguities and inconsistencies.
2 Revised5.91 Scheme
INTRODUCTION
Programming languages should be designed not by piling As Scheme became more widespread, local dialects be-
feature on top of feature, but by removing the weaknesses gan to diverge until students and researchers occasion-
and restrictions that make additional features appear nec- ally found it difficult to understand code written at other
essary. Scheme demonstrates that a very small number of sites. Fifteen representatives of the major implementations
rules for forming expressions, with no restrictions on how of Scheme therefore met in October 1984 to work toward
they are composed, suffice to form a practical and efficient a better and more widely accepted standard for Scheme.
programming language that is flexible enough to support Their report [7], edited by Will Clinger, was published at
most of the major programming paradigms in use today. MIT and Indiana University in the summer of 1985. Fur-
ther revision took place in the spring of 1986 [42] (edited
Scheme was one of the first programming languages to in-
by Jonathan Rees and Will Clinger), and in the spring of
corporate first class procedures as in the lambda calculus,
1988 [9] (also edited by Will Clinger and Jonathan Rees).
thereby proving the usefulness of static scope rules and
Another revision published in 1998, edited by Richard
block structure in a dynamically typed language. Scheme
Kelsey, Will Clinger and Jonathan Rees, reflected further
was the first major dialect of Lisp to distinguish procedures
revisions agreed upon in a meeting at Xerox PARC in June
from lambda expressions and symbols, to use a single lex-
1992 [28].
ical environment for all variables, and to evaluate the op-
erator position of a procedure call in the same way as an Attendees of the Scheme Workshop in Pittsburgh in Octo-
operand position. By relying entirely on procedure calls ber 2002 formed a Strategy Committee to discuss a process
to express iteration, Scheme emphasized the fact that tail- for producing new revisions of the report. The strategy
recursive procedure calls are essentially goto’s that pass committee drafted a charter for Scheme standardization.
arguments. Scheme was the first widely used program- This charter, together with a process for selecting editors’
ming language to embrace first class escape procedures, committees for producing new revisions for the report, was
from which all previously known sequential control struc- confirmed by the attendees of the Scheme Workshop in
tures can be synthesized. A subsequent version of Scheme Boston in November 2003. Subsequently, a Steering Com-
introduced the concept of exact and inexact numbers, an mittee according to the charter was selected, consisting of
extension of Common Lisp’s generic arithmetic. More re- Alan Bawden, Guy L. Steele Jr., and Mitch Wand. An
cently, Scheme became the first programming language to editors’ committee charged with producing this report was
support hygienic macros, which permit the syntax of a also formed at the end of 2003, consisting of Will Clinger,
block-structured language to be extended in a consistent R. Kent Dybvig, Marc Feeley, Matthew Flatt, Richard
and reliable manner. Kelsey, Manuel Serrano, and Mike Sperber, with Marc Fee-
ley acting as Editor-in-Chief. Richard Kelsey resigned from
Numerical computation was long neglected by the Lisp
the committee in April 2005, and was replaced by Anton
community. Until Common Lisp there was no carefully
van Straaten. Marc Feeley and Manuel Serrano resigned
thought out strategy for organizing numerical computa-
from the committee in January 2006. Subsequently, the
tion, and with the exception of the MacLisp system [39]
charter was revised to reduce the size of the editors’ com-
little effort was made to execute numerical code efficiently.
mittee to five and to replace the office of Editor-in-Chief by
The Scheme reports recognized the excellent work of the
a Chair and a Project Editor [48]. R. Kent Dybvig served
Common Lisp committee and accepted many of their rec-
as Chair, and Mike Sperber served as Project Editor. Parts
ommendations, while simplifying and generalizing in some
of the report were posted as Scheme Requests for Imple-
ways consistent with the purposes of Scheme.
mentation (SRFIs) and discussed by the community before
being revised and finalized for the report [22, 12, 13, 21, 17].
Background Jacob Matthews and Robby Findler wrote the operational
semantics for the language core.
The first description of Scheme was written by Gerald Jay
Sussman and Guy Lewis Steele Jr. in 1975 [47]. A revised We intend this report to belong to the entire Scheme com-
report by Steele and Sussman [44] appeared in 1978 and munity, and so we grant permission to copy it in whole or in
described the evolution of the language as its MIT imple- part without fee. In particular, we encourage implementors
mentation was upgraded to support an innovative com- of Scheme to use this report as a starting point for manuals
piler [45]. Three distinct projects began in 1981 and 1982 and other documentation, modifying it as necessary.
to use variants of Scheme for courses at MIT, Yale, and
Indiana University [40, 36, 19]. An introductory computer Acknowledgements
science textbook using Scheme was published in 1984 [1].
A number of textbooks describing und using Scheme have We would like to thank the following people for their
been published since [15]. help: Alan Bawden, Michael Blair, Per Bothner, Thomas
4 Revised5.91 Scheme
Characters Scheme characters mostly correspond to In the first of these examples, +, the operator, is the name
textual characters. More precisely, they are isomorphic of the built-in operation for addition, and 23 and 42 are the
to the scalar values of the Unicode standard. operands. The expression (+ 23 42) reads as “the sum of
23 and 42.” Compound expressions can be nested—the
second example reads as “the sum of 14 and the product
Strings Strings are finite sequences of characters with of 23 and 42.”
fixed length and thus represent arbitrary Unicode texts.
As these examples indicate, compound expressions in
Scheme are always written using the same prefix nota-
Symbols A symbol is an object representing a string tion. As a consequence, the parentheses are needed to
that cannot be modified. This string is called the symbol’s indicate structure, and “superfluous” parentheses, which
name. Unlike strings, two symbols whose names are spelled are permissible in mathematics and many programming
the same way are indistinguishable. Symbols are useful for languages, are not allowed in Scheme.
many applications; for instance, they may be used the way
As in many other languages, whitespace and newlines are
enumerated values are used in other languages.
not significant when they separate subexpressions of an
expression, and can be used to indicate structure.
Pairs and lists A pair is a data structure with two com-
ponents. The most common use of pairs is to represent
(singly linked) lists, where the first component (the “car”) 1.3. Variables and binding
represents the first element of the list, and the second com-
ponent (the “cdr”) the rest of the list. Scheme also has a Scheme allows identifiers to denote values. These identi-
distinguished empty list, which is the last cdr in a chain of fiers are called variables. (More precisely, variables denote
pairs representing a list. locations. This distinction is not important, however, for
a large proportion of Scheme code.)
Vectors Vectors, like lists, are linear data structures rep- (let ((x 23)
resenting finite sequences of arbitrary objects. Whereas the (y 42))
elements of a list are accessed sequentially through the pair (+ x y)) =⇒ 65
chain representing it, the elements of a vector are addressed
by an integer index. Thus, vectors are more appropriate In this case, the operator of the expression, let, is a bind-
than lists for random access to elements. ing construct. The parenthesized structure following the
let lists variables alongside expressions: the variable x
alongside 23, and the variable y alongside 42. The let
Procedures As mentioned in the introduction, proce- expression binds x to 23, and y to 42. These bindings are
dures are values in Scheme. available in the body of the let expression, (+ x y), and
only there.
1.2. Expressions
1.4. Definitions
The most important elements of a Scheme program are
expressions. Expressions can be evaluated, producing a The variables bound by a let expression are local, because
value. (Actually, any number of values—see section 4.5.) their bindings are visible only in the let’s body. Scheme
The most fundamental expressions are literal expressions: also allows creating top-level bindings for identifiers as fol-
lows:
#t =⇒ #t
23 =⇒ 23 (define x 23)
(define y 42)
This notation means that the expression #t evaluates to (+ x y) =⇒ 65
#t, that is, the value for “true,” and that the expression
23 evaluates to the number 23. (These are actually “top-level” in the body of a library or
Compound expressions are formed by placing parentheses script; see section 1.10 below.)
around their subexpressions. The first subexpression is an The first two parenthesized structures are definitions; they
operator and identifies an operation; the remaining subex- create top-level bindings, binding x to 23 and y to 42. Defi-
pressions are operands: nitions are not expressions, and cannot appear in all places
(+ 23 42) =⇒ 65 where an expression can occur. Moreover, a definition has
(+ 14 (* 23 42)) =⇒ 980 no value.
1. Overview of Scheme 7
Bindings follow the lexical structure of the program: When Procedure definitions are not the only way to create pro-
several bindings with the same name exist, a variable refers cedures. A lambda expression creates a new procedure as
to the binding that is closest to it, starting with its occur- a value, with no need to specify a name:
rence in the program and going from inside to outside,
going all the way to a top-level binding only if no local ((lambda (x) (+ x 42)) 23) =⇒ 65
binding can be found along the way:
The entire expression in this example is a procedure call;
(define x 23) its operator is (lambda (x) (+ x 42)), which evaluates
(define y 42) to a procedure that takes a single number and add it to
(let ((y 43)) 42.
(+ x y)) =⇒ 66
(define (g p x)
(p x)) 1.7. Assignment
1.8. Derived forms and macros be represented in textual form as a syntactic datum, which
can be written out and read back in without loss of infor-
Many of the special forms specified in this report can mation. Several syntactic datums can represent the same
be translated into more basic special forms. For exam- datum value, but the datum value corresponding to a syn-
ple, let expressions can be translated into procedure calls tactic datum is uniquely determined. Moreover, each da-
and lambda expressions. The following two expressions are tum value can be trivially translated to a literal expression
equivalent: in a program by prepending a ’ to a corresponding syntac-
(let ((x 23) tic datum:
(y 42)) ’23 =⇒ 23
(+ x y)) =⇒ 65 ’#t =⇒ #t
’foo =⇒ foo
((lambda (x y) (+ x y)) 23 42) ’(1 2 3) =⇒ (1 2 3)
=⇒ 65 ’#(1 2 3) =⇒ #(1 2 3)
Special forms like let expressions are called derived forms The ’ is, of course, not needed for number or boolean lit-
because their semantics can be derived from that of other erals. The identifier foo is a syntactic datum that can
kinds of forms by a syntactic transformation. Procedure represent a symbol with name “foo,” and ’foo is a literal
definitions are also derived forms. The following two defi- expression with that symbol as its value. (1 2 3) is a syn-
nitions are equivalent: tactic datum that can represent a list with elements 1, 2,
(define (f x) and 3, and ’(1 2 3) is a literal expression with this list
(+ x 42)) as its value. Likewise, #(1 2 3) is a syntactic datum that
can represent a vector with elements 1, 2 and 3, and ’#(1
(define f 2 3) is the corresponding literal.
(lambda (x) The syntactic datums form a superset of the Scheme forms.
(+ x 42)))
Thus, datums can be used to represent Scheme programs
In Scheme, it is possible for a program to create its own as data objects. In particular, symbols can be used to
derived forms by binding syntactic keywords to macros: represent identifiers.
1.11. Scripts
1.9. Syntactic datums and datum values
A Scheme program is invoked via a script. Like a library,
A subset of the Scheme values called datum values have a script contains declarations, definitions and expressions,
a special status in the language. These include booleans, but specifies an entry point for execution. Thus, a script
numbers, characters, and strings as well as lists and vec- defines, via the transitive closure of the libraries it imports,
tors whose elements are datums. Each datum value may a Scheme program.
2. Numbers 9
#! /usr/bin/env scheme-script algebra system. On the other hand, the results of measure-
#!r6rs ments are inherently inexact, and irrational numbers may
(import (r6rs base) be approximated by rational and therefore inexact approx-
(r6rs i/o ports)) imations. In order to catch uses of inexact numbers where
(put-bytes (standard-output-port) exact numbers are required, Scheme explicitly distinguishes
(call-with-port
exact from inexact numbers. This distinction is orthogonal
(open-file-input-port
(cadr (command-line-arguments)))
to the dimension of type.
get-bytes-all)) A fixnum is an exact integer whose value lies within a cer-
0 tain implementation-dependent subrange of the exact inte-
gers (section 16.3). Likewise, every implementation is re-
quired to designate a subset of its inexact reals as flonums,
2. Numbers and to convert certain external representations into flon-
This chapter describes Scheme’s representations for num- ums. Note that this does not imply that an implementation
bers. It is important to distinguish between the mathemat- is required to use floating point representations.
ical numbers, the Scheme numbers that attempt to model
them, the machine representations used to implement the
Scheme numbers, and notations used to write numbers. 2.2. Exactness
This report uses the types number, complex, real, ratio-
nal, and integer to refer to both mathematical numbers Scheme numbers are either exact or inexact. A number
and Scheme numbers. The fixnum and flonum types refer is exact if it is written as an exact constant or was de-
to certain subtypes of the Scheme numbers, as explained rived from exact numbers using only exact operations. A
below. number is inexact if it is written as an inexact constant
or was derived from inexact numbers. Thus inexactness is
contagious.
2.1. Numerical types
Exact arithmetic is reliable in the following sense: If ex-
Mathematically, numbers may be arranged into a tower of act numbers are passed to any of the arithmetic proce-
subtypes in which each level is a subset of the level above dures described in section 9.10, and an exact number is re-
it: turned, then the result is mathematically correct. This is
generally not true of computations involving inexact num-
number bers because approximate methods such as floating point
complex arithmetic may be used, but it is the duty of each imple-
real mentation to make the result as close as practical to the
rational mathematically ideal result.
integer
For example, 5 is an integer. Therefore 5 is also a rational,
a real, and a complex. The same is true of the Scheme 2.3. Implementation restrictions
numbers that model 5. For Scheme numbers, these types
are defined by the predicates number?, complex?, real?, Implementations of Scheme are required to implement the
rational?, and integer?. whole tower of subtypes given in section 2.1.
There is no simple relationship between a number’s type Implementations are required to support exact integers and
and its representation inside a computer. Although most exact rationals of practically unlimited size and precision,
implementations of Scheme offer at least three different and to implement certain procedures (listed in 9.10.1) so
representations of 5, these different representations denote they always return exact results when given exact argu-
the same integer. ments.
Scheme’s numerical operations treat numbers as abstract Implementations may support only a limited range of in-
data, as independent of their representation as possible. exact numbers of any type, subject to the requirements of
Although an implementation of Scheme may use many dif- this section. For example, an implementation may limit
ferent representations for numbers, this should not be ap- the range of inexact reals (and therefore the range of in-
parent to a casual programmer writing simple programs. exact integers and rationals) to the dynamic range of the
It is necessary, however, to distinguish between numbers flonum format. Furthermore the gaps between the repre-
that are represented exactly and those that may not be. sentable inexact integers and rationals are likely to be very
For example, indexes into data structures must be known large in such an implementation as the limits of this range
exactly, as must some polynomial coefficients in a symbolic are approached.
10 Revised5.91 Scheme
An implementation may use floating point and other ap- Syntactic datums (also called external representations)
proximate representation strategies for inexact numbers. double as a notation for data, and Scheme’s (r6rs i/o
This report recommends, but does not require, that the ports) library (section 15.3) provides the get-datum and
IEEE floating point standards be followed by implemen- put-datum procedures for reading and writing syntactic
tations that use floating point representations, and that datums, converting between their textual representation
implementations using other representations should match and the corresponding values. A syntactic datum can be
or exceed the precision achievable using these floating point used in a program to obtain the corresponding value using
standards [26]. quote (see section 9.5.1).
In particular, implementations that use floating point rep- Moreover, valid Scheme expressions form a subset of the
resentations must follow these rules: A floating point result syntactic datums. Consequently, Scheme’s syntax has the
must be represented with at least as much precision as is property that any sequence of characters that is an expres-
used to express any of the inexact arguments to that op- sion is also a syntactic datum representing some object.
eration. It is desirable (but not required) for potentially This can lead to confusion, since it may not be obvious
inexact operations such as sqrt, when applied to exact ar- out of context whether a given sequence of characters is
guments, to produce exact answers whenever possible (for intended to denote data or program. It is also a source
example the square root of an exact 4 ought to be an exact of power, since it facilitates writing programs such as in-
2). If, however, an exact number is operated upon so as to terpreters and compilers that treat programs as data (or
produce an inexact result (as by sqrt), and if the result is vice versa). A syntactic datum occurring in program text
represented in floating point, then the most precise float- is often called a form.
ing point format available must be used; but if the result
is represented in some other way then the representation Note that several syntactic datums may represent the
must have at least as much precision as the most precise same object, a so-called datum value. For example,
floating point format available. both“#e28.000” and “#x1c” are syntactic datums repre-
senting the exact integer 28; The syntactic datums “(8
It is the programmer’s responsibility to avoid using inex- 13)”, “( 08 13 )”, “(8 . (13 . ()))” (and more) all
act numbers with magnitude or significand too large to be represent a list containing the integers 8 and 13. Syntactic
represented in the implementation. datums that denote equal objects are always equivalent as
forms of a program.
2.4. Infinities and NaNs Because of the close correspondence between syntactic da-
tums and datum values, this report sometimes uses the
Positive infinity is regarded as a real (but not rational) term datum to denote either a syntactic datum or a da-
number, whose value is indeterminate but greater than all tum value when the exact meaning is apparent from the
rational numbers. Negative infinity is regarded as a real context.
(but not rational) number, whose value is indeterminate
but less than all rational numbers. An implementation is not permitted to extend the lexical
or read syntax in any way, with one exception: it need
A NaN is regarded as a real (but not rational) number not treat the syntax #!hidentifieri, for any hidentifieri (see
whose value is so indeterminate that it might represent section 3.2.3) that is not r6rs, as a syntax violation, and it
any real number, including positive or negative infinity, may use specific #!-prefixed identifiers as flags indicating
and might even be greater than positive infinity or less that subsequent input contains extensions to the standard
than negative infinity. lexical syntax. (The comment syntax #!r6rs may be used
to signify that the input which follows is written purely in
3. Lexical syntax and read syntax the language described by this report; see section 3.2.2.)
The syntax of Scheme programs is organized in three levels: This chapter overviews and provides formal accounts of the
lexical syntax and the read syntax.
1. the lexical syntax that describes how a program text
is split into a sequence of lexemes,
2. the read syntax, formulated in terms of the lexical syn- 3.1. Notation
tax, that structures the lexeme sequence as a sequence
of syntactic datums, where a syntactic datum is a re- The formal syntax for Scheme is written in an extended
cursively structured entity, BNF. Non-terminals are written using angle brackets; case
is insignificant for non-terminal names.
3. the program syntax formulated in terms of the read
syntax, imposing further structure and assigning All spaces in the grammar are for legibility. hEmptyi
meaning to syntactic datums. stands for the empty string.
3. Lexical syntax and read syntax 11
The following extensions to BNF are used to make the de- linefeedi
scription more concise: hthingi* means zero or more occur- | hnested commenti
rences of hthingi; and hthingi+ means at least one hthingi. | #; hdatumi
| #!r6rs
Some non-terminal names refer to the Unicode scalar val-
hnested commenti −→ #| hcomment texti
ues of the same name: hcharacter tabulationi (U+0009),
hcomment conti* |#
hlinefeedi (U+000A), hline tabulationi (U+000B),
hcomment texti −→ hcharacter sequence not containing
hform feedi (U+000C), hcarriage returni (U+000D),
#| or |#i
and hspacei (U+0020).
hcomment conti −→ hnested commenti hcomment texti
hatmospherei −→ hwhitespacei | hcommenti
3.2. Lexical syntax hinterlexeme spacei −→ hatmospherei*
The lexical syntax describes how a character sequence is hidentifieri −→ hinitiali hsubsequenti*
split into a sequence of lexemes, omitting non-significant | hpeculiar identifieri
portions such as comments and whitespace. The charac- hinitiali −→ hconstituenti | hspecial initiali
ter sequence is assumed to be text according to the Uni- | hsymbol escapei
code standard [51]. Some of the lexemes, such as numbers, hletteri −→ a | b | c | ... | z
identifiers, strings etc. of the lexical syntax are syntactic | A | B | C | ... | Z
datums in the read syntax, and thus represent data. Be- hconstituenti −→ hletteri
sides the formal account of the syntax, this section also | hany character whose scalar value is greater than
describes what datum values are denoted by these syntac- 127, and whose category is Lu, Lt, Lm, Lo, Mn, Mc,
tic datums. Me, Nd, Nl, No, Pd, Pc, Po, Sc, Sm, Sk, So, or Coi
Note that the lexical syntax, in the description of com- hspecial initiali −→ ! | $ | % | & | * | / | : | < | =
ments, contains a forward reference to hdatumi, which is | > | ? | ^ | _ | ~
described as part of the read syntax. However, being com- hsubsequenti −→ hinitiali | hdigiti
ments, these hdatumis do not play a significant role in the | hspecial subsequenti
syntax. | hinline hex escapei
Case is significant except in boolean datums, number da- hdigiti −→ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
tums, and hexadecimal numbers denoting scalar values. hhex digiti −→ hdigiti
For example, #x1A and #X1a are equivalent. The identi- | a | A | b | B | c | C | d | D | e | E | f | F
fier Foo is, however, distinct from the identifier FOO. hspecial subsequenti −→ + | - | . | @
hinline hex escapei −→ \xhhex scalar valuei;
hhex scalar valuei −→ hhex digiti+
3.2.1. Formal account with at most 8 digits
hpeculiar identifieri −→ + | - | ... | -> hsubsequenti*
hInterlexeme spacei may occur on either side of any lexeme, hbooleani −→ #t | #T | #f | #F
but not within a lexeme. hcharacteri −→ #\hany characteri
Lexemes that require implicit termination (identifiers, | #\hcharacter namei
numbers, characters, booleans, and dot) are terminated | #\xhhex scalar valuei
by any hdelimiteri or by the end of the input, but not nec- hcharacter namei −→ nul | alarm | backspace | tab
essarily by anything else. | linefeed | vtab | page | return | esc
| space | delete
The following two characters are reserved for future exten-
sions to the language: { }
hstringi −→ " hstring elementi* "
hlexemei −→ hidentifieri | hbooleani | hnumberi hstring elementi −→ hany character other than " or \i
| hcharacteri | hstringi | \a | \b | \t | \n | \v | \f | \r
| ( | ) | [ | ] | #( | ’ | ` | , | ,@ | . | \" | \\
hdelimiteri −→ hwhitespacei | ( | ) | [ | ] | " | ; | \hlinefeedi | \hspacei
hwhitespacei −→ hcharacter tabulationi | hlinefeedi | hinline hex escapei
| hline tabulationi | hform feedi hcarriage returni
| hany character whose category is Zs, Zl, or Zpi
hintra-line whitespacei −→ hany hwhitespacei hnumberi −→ hnum 2i | hnum 8i
that is not hlinefeedi | hnum 10i | hnum 16i
hcommenti −→ ; hall subsequent characters up to a
12 Revised5.91 Scheme
The following rules for hnum Ri, hcomplex Ri, hreal Ri, The lexical syntax includes several comment forms. In all
hureal Ri, huinteger Ri, and hprefix Ri should be repli- cases, comments are invisible to Scheme, except that they
cated for R = 2, 8, 10, and 16. There are no rules for act as delimiters, so a comment cannot appear in the mid-
hdecimal 2i, hdecimal 8i, and hdecimal 16i, which means dle of an identifier or number.
that numbers containing decimal points or exponents must A semicolon (;) indicates the start of a line comment. The
be in decimal radix. comment continues to the end of the line on which the
semicolon appears (i.e., it is terminated by a linefeed char-
hnum Ri −→ hprefix Ri hcomplex Ri
acter).
hcomplex Ri −→ hreal Ri | hreal Ri @ hreal Ri
| hreal Ri + hureal Ri i | hreal Ri - hureal Ri i Another way to indicate a comment is to prefix a hdatumi
| hreal Ri + i | hreal Ri - i (cf. Section 3.3.1) with #;, possibly with whitespace before
| + hureal Ri i | - hureal Ri i | + i | - i the hdatumi. The comment consists of the comment prefix
hreal Ri −→ hsigni hureal Ri #; and the hdatumi together. (This notation is useful for
hureal Ri −→ huinteger Ri “commenting out” sections of code.)
| huinteger Ri / huinteger Ri Block comments may be indicated with properly nested #|
| hdecimal Ri hmantissa widthi and |# pairs.
| inf.0 | nan.0
hdecimal 10i −→ huinteger 10i hsuffixi #|
| . hdigit 10i+ #* hsuffixi The FACT procedure computes the factorial
| hdigit 10i+ . hdigit 10i* #* hsuffixi of a non-negative integer.
|#
| hdigit 10i+ #+ . #* hsuffixi
(define fact
huinteger Ri −→ hdigit Ri+ #*
(lambda (n)
hprefix Ri −→ hradix Ri hexactnessi ;; base case
| hexactnessi hradix Ri (if (= n 0)
#;(= n 1)
1 ; identity of *
hsuffixi −→ hemptyi (* n (fact (- n 1))))))
| hexponent markeri hsigni hdigit 10i+
hexponent markeri −→ e | E | s | S | f | F The lexeme #!r6rs is also a comment. When it occurs
| d | D | l | L in program text, it signifies that program text to be writ-
hmantissa widthi −→ hemptyi ten purely in the language described by this report (see
| | hdigit 10i+ section 6.1).
hsigni −→ hemptyi | + | -
hexactnessi −→ hemptyi 3.2.3. Identifiers
| #i | #I | #e | #E
hradix 2i −→ #b | #B Most identifiers allowed by other programming languages
hradix 8i −→ #o | #O are also acceptable to Scheme. In particular, a sequence of
hradix 10i −→ hemptyi | #d | #D letters, digits, and “extended alphabetic characters” that
hradix 16i −→ #x | #X begins with a character that cannot begin a number is an
hdigit 2i −→ 0 | 1 identifier. In addition, +, -, and ... are identifiers. Here
hdigit 8i −→ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 are some examples of identifiers:
hdigit 10i −→ hdigiti
lambda q
hdigit 16i −→ hhex digiti
list->vector soup
+ V17a
<=? a34kTMNs
the-word-recursion-has-many-meanings
3.2.2. Whitespace and comments
Extended alphabetic characters may be used within iden-
Whitespace characters are spaces, linefeeds, carriage re- tifiers as if they were letters. The following are extended
turns, character tabulations, form feeds, line tabulations, alphabetic characters:
and any other character whose category is Zs, Zl, or Zp.
! $ % & * + - . / : < = > ? @ ^ _ ~
Whitespace is used for improved readability and as nec-
essary to separate lexemes from each other. Whitespace Moreover, all characters whose scalar values are greater
may occur between any two lexemes, but not within a lex- than 127 and whose Unicode category is Lu, Lt, Lm, Lo,
eme. Whitespace may also occur inside a string, where it Mn, Mc, Me, Nd, Nl, No, Pd, Pc, Po, Sc, Sm, Sk, So, or Co
is significant. can be used within identifiers. Moreover, any character can
3. Lexical syntax and read syntax 13
• \xhdigit 16i+ ; : (note the terminating semi-colon) In systems with inexact numbers of varying precisions, it
where no more than eight hdigit 16is are provided, may be useful to specify the precision of a constant. For
and the sequence of hdigit 16is forms a hexadecimal this purpose, numerical constants may be written with an
number between 0 and #x10FFFF excluding the range exponent marker that indicates the desired precision of the
[#xD800, #xDFFF]. inexact representation. The letters s, f, d, and l specify
the use of short, single, double, and long precision, respec-
tively. (When fewer than four internal inexact represen-
These escape sequences are case-sensitive, except that
tations exist, the four size specifications are mapped onto
hdigit 16i can be an uppercase or lowercase hexadecimal
those available. For example, an implementation with two
digit.
internal representations may map short and single together
Any other character in a string after a backslash is an er- and long and double together.) In addition, the exponent
ror. Any character outside of an escape sequence and not marker e specifies the default precision for the implemen-
a doublequote stands for itself in the string literal. For tation. The default precision has at least as much precision
example the single-character string "λ" (double quote, a as double, but implementations may wish to allow this de-
lower case lambda, double quote) denotes the same string fault to be set by the user.
literal as "\x03bb;".
3.14159265358979F0
Examples: Round to single — 3.141593
0.6L0
"abc" =⇒ U+0061, U+0062, U+0063 Extend to long — .600000000000000
"\x41;bc" =⇒ "Abc" ; U+0041, U+0062, U+0063
"\x41; bc" =⇒ "A bc" If x is an external representation of an inexact real number
; U+0041, U+0020, U+0062, U+0063 that contains no vertical bar, and p is a sequence of 1 or
"\x41bc;" =⇒ U+41BC more decimal digits, then x |p is an external representation
"\x41" =⇒ &lexical exception that denotes the best binary floating point approximation
"\x;" =⇒ &lexical exception to x using a p-bit significand. For example, 1.1|53 is an
"\x41bx;" =⇒ &lexical exception
external representation for the best approximation to 1.1
"\x00000041;" =⇒ "A" ; U+0041
"\x0010FFFF;" =⇒ U+10FFFF
in IEEE double precision.
"\x00110000;" =⇒ &lexical exception If x is an external representation of an inexact real number
; out of range that contains no vertical bar, then x by itself should be
"\x000000001;"=⇒ &lexical exception regarded as equivalent to x |53.
; too many digits
"\xD800;" =⇒ &lexical exception Implementations that use binary floating point representa-
; in excluded range tions of real numbers should represent x |p using a p-bit
significand if practical, or by a greater precision if a p-
bit significand is not practical, or by the largest available
precision if p or more bits of significand are not practical
3.2.7. Numbers within the implementation.
The syntax of written representations for numbers is de- Note: The precision of a significand should not be confused
scribed formally by the hnumberi rule in the formal gram- with the number of bits used to represent the significand. In
the IEEE floating point standards, for example, the significand’s
mar. Note that case is not significant in numerical con-
most significant bit is implicit in single and double precision but
stants. is explicit in extended precision. Whether that bit is implicit or
A number may be written in binary, octal, decimal, or hex- explicit does not affect the mathematical precision. In imple-
adecimal by the use of a radix prefix. The radix prefixes mentations that use binary floating point, the default precision
are #b (binary), #o (octal), #d (decimal), and #x (hexadec- can be calculated by calling the following procedure:
imal). With no radix prefix, a number is assumed to be (define (precision)
expressed in decimal. (do ((n 0 (+ n 1))
(x 1.0 (/ x 2.0)))
A numerical constant may be specified to be either exact or
((= 1.0 (+ 1.0 x)) n)))
inexact by a prefix. The prefixes are #e for exact, and #i
for inexact. An exactness prefix may appear before or after
any radix prefix that is used. If the written representation Note: When the underlying floating-point representation is
of a number has no exactness prefix, the constant may be IEEE double precision, the |p suffix should not always be
either inexact or exact. It is inexact if it contains a decimal omitted: Denormalized numbers have diminished precision, and
point, an exponent, or a “#” character in the place of a therefore should carry a |p suffix with the actual width of the
digit; otherwise it is exact. significand.
3. Lexical syntax and read syntax 15
The literals +inf.0 and -inf.0 represent positive and neg- | [hdatumi+ . hdatumi]
ative infinity, respectively. The +nan.0 literal represents | habbreviationi
the NaN that is the result of (/ 0.0 0.0), and may rep- habbreviationi −→ habbrev prefixi hdatumi
resent other NaNs as well. habbrev prefixi −→ ’ | ` | , | ,@ | #’ | #` | #, | #,@
hvectori −→ #(hdatumi*)
If a hdecimal 10i contains no vertical bar and does not
hbytesi −→ #vu8(hu8i*)
contain one of the exponent markers s, f, d, or l, but does
hu8i −→ hany hnumberi denoting an exact
contain a decimal point or the exponent marker e, then
integer in {0, . . . , 255}i
it is an external representation for a flonum. Furthermore
inf.0, +inf.0, -inf.0, nan.0, +nan.0, and -nan.0 are
external representations for flonums. Some or all of the
3.3.2. Vectors
other external representations for inexact reals may also
represent flonums, but that is not required by this report.
Vector datums, denoting vectors of values (see section 9.16,
If a hdecimal 10i contains a non-empty hmantissa widthi or are written using the notation #(hdatumi . . . ). For exam-
one of the exponent markers s, f, d, or l, then it represents ple, a vector of length 3 containing the number zero in
an inexact number, but does not necessarily represent a element 0, the list (2 2 2 2) in element 1, and the string
flonum. "Anna" in element 2 can be written as following:
#(0 (2 2 2 2) "Anna")
3.3. Read syntax
Note that this is the external representation of a vector,
The read syntax describes the syntax of syntactic datums and is not a base-library expression that evaluates to a
in terms of a sequence of hlexemeis, as defined in the lexical vector.
syntax.
Syntactic datums include the lexeme datums described in 3.3.3. Pairs and lists
the previous section as well as the following constructs for
forming compound structure: List and pair datums, denoting pairs and lists of values
(see section 9.12) are written using parentheses or brackets.
• pairs and lists, enclosed by ( ) or [ ] (see sec- Matching pairs of parentheses that occur in the rules of
tion 3.3.3) hlisti are equivalent to matching pairs of brackets.
• vectors (see section 3.3.2) The most general notation for Scheme pairs as syntactic
datums is the “dotted” notation (hdatum1 i . hdatum2 i)
Note that the sequence of characters “(+ 2 6)” is not a where hdatum1 i is the representation of the value of the
syntactic datum representing the integer 8, even though car field and hdatum2 i is the representation of the value of
it is a base-library expression evaluating to the integer 8; the cdr field. For example (4 . 5) is a pair whose car is
rather, it is a datum representing a three-element list, the 4 and whose cdr is 5. Note that (4 . 5) is the external
elements of which are the symbol + and the integers 2 and representation of a pair, not an expression that evaluates
6. to a pair.
A more streamlined notation can be used for lists: the
elements of the list are simply enclosed in parentheses and
3.3.1. Formal account
separated by spaces. The empty list is written () . For
The following grammar describes the syntax of syntactic example,
datums in terms of various kinds of lexemes defined in the
(a b c d e)
grammar in section 3.2:
hdatumi −→ hsimple datumi and
| hcompound datumi
(a . (b . (c . (d . (e . ())))))
hsimple datumi −→ hbooleani | hnumberi
| hcharacteri | hstringi | hsymboli
are equivalent notations for a list of symbols.
hsymboli −→ hidentifieri
hcompound datumi −→ hlisti | hvectori The general rule is that, if a dot is followed by an open
hlisti −→ (hdatumi*) parenthesis, the dot, the open parenthesis, and the match-
| [hdatumi*] ing closing parenthesis can be omitted in the external rep-
| (hdatumi+ . hdatumi) resentation.
16 Revised5.91 Scheme
3.3.4. Bytes objects terms of other standard procedures or syntactic forms are
not part of the base library, but are defined in separate
Bytes datums, denoting bytes objects (see section 11), are libraries. Examples include the fixnums and flonums li-
written using the notation #vu8(hu8i . . . ), where the hu8is braries, the exceptions and conditions libraries, and the
repersent the octets of the bytes object. For example, a libraries for records.
bytes object of length 3 containing the octets 2, 24, and
123 can be written as follows:
#vu8(2 24 123)
4.2. Variables, syntactic keywords, and re-
Note that this is the external representation of a bytes gions
object, and is not an expression that evaluates to a bytes
object.
In a library body, an identifier may name a type of syntax,
or it may name a location where a value can be stored. An
3.3.5. Abbreviations
identifier that names a type of syntax is called a syntactic
keyword and is said to be bound to that syntax. An identi-
’hdatumi fier that names a location is called a variable and is said to
`hdatumi be bound to that location. The set of all visible bindings
,hdatumi in effect at some point in a program is known as the en-
,@hdatumi vironment in effect at that point. The value stored in the
#’hdatumi location to which a variable is bound is called the variable’s
#`hdatumi value. By abuse of terminology, the variable is sometimes
#,hdatumi said to name the value or to be bound to the value. This
#,@hdatumi is not quite accurate, but confusion rarely results from this
practice.
Each of these is an abbreviation:
’hdatumi for (quote hdatumi), Certain expression types are used to create new kinds
`hdatumi for (quasiquote hdatumi), of syntax and to bind syntactic keywords to those new
,hdatumi for (unquote hdatumi), syntaxes, while other expression types create new loca-
,@hdatumi for (unquote-splicing hdatumi), tions and bind variables to those locations. These ex-
#’hdatumi for (syntax hdatumi), pression types are called binding constructs. The con-
#`hdatumi for (quasisyntax hdatumi), structs in the base library that bind syntactic keywords
#,hdatumi for (unsyntax hdatumi), and are listed in section 6.3.2. The most fundamental of the
#,@hdatumi for (unsyntax-splicing hdatumi). variable binding constructs is the lambda expression, be-
cause all other variable binding constructs can be explained
in terms of lambda expressions. The other variable binding
4. Semantic concepts constructs are let, let*, letrec*, letrec, let-values,
4.1. Programs and libraries let*-values, do, and case-lambda expressions (see sec-
tions 9.5.2, 9.5.6, 9.19, and 20.2).
A Scheme program consists of a script together with a set of Like Algol and Pascal, and unlike most other dialects of
libraries, each of which defines a part of the program con- Lisp except for Common Lisp, Scheme is a statically scoped
nected to the others through explicitly specified exports language with block structure. To each place where an
and imports. A library consists of a set of export and identifier is bound in a program there corresponds a region
import specifications and a body, which consists of decla- of the program text within which the binding is visible.
rations, definitions, and expressions; a script is similar to a The region is determined by the particular binding con-
library, but has no export specifications. Chapters 6 and 7 struct that establishes the binding; if the binding is estab-
describe the syntax and semantics of libraries and scripts, lished by a lambda expression, for example, then its region
respectively. Subsequent chapters describe various stan- is the entire lambda expression. Every mention of an iden-
dard libraries provided by a Scheme system. In particular, tifier refers to the binding of the identifier that established
chapter 9 describes a base library that defines many of the the innermost of the regions containing the use. If there
constructs traditionally associated with Scheme programs. is no binding of the identifier whose region contains the
The division between the base library and other standard use, then the use refers to the binding for the variable in
libraries is based on use, not on construction. In particular, the top level environment of the library body or a binding
some facilities that are typically implemented as “primi- imported from another library. (See chapter 6.) If there is
tives” by a compiler or run-time libraries rather than in no binding for the identifier, it is said to be unbound.
4. Semantic concepts 17
4.3. Exceptional situations in ways that are inconsistent with the semantics described
in this document, unless said execution first encounters
A variety of exceptional situations are distinguished in this some implementation restriction or other defect in the im-
report, among them violations of program syntax, viola- plementation of Scheme that is executing the script.
tions of a procedure’s specification, violations of imple- Violations of an implementation restriction
mentation restrictions, and exceptional situations in the must raise an exception with condition type
environment. When an exception is raised, an object is &implementation-restriction, as must all violations
provided that describes the nature of the exceptional siu- and errors that would otherwise threaten system integrity
tation. The report uses the condition system described in in ways that might result in execution that is inconsistent
section 14.2 to describe exceptional situations, classifying with the semantics described in this document.
them by condition types.
The above safety properties are guaranteed only for scripts
For most of the exceptional situations described in this re- and libraries that are said to be safe. Implementations may
port, portable programs cannot rely upon the exception provide access to unsafe libraries, and may interpret (safe
being continuable at the place where the situation was de- 0) and unsafe declarations in ways that cannot guarantee
tected. For those exceptions, the exception handler that safety.
is invoked by the exception should not return. In some
cases, however, continuing is permissible; the handler may
return. See section 14.1. 4.5. Multiple return values
An implementation restriction is a limitation imposed by
an implementation. Implementations are required to raise A Scheme expression can evaluate to an arbitrary finite
an exception when they are unable to continue correct ex- number of values. These values are passed to the expres-
ecution of a correct program due to some implementation sion’s continuation.
restriction.
Not all continuations accept any number of values: A con-
Some possible implementation restrictions such as the lack tinuation that accepts the argument to a procedure call is
of representations for NaNs and infinities (see section 16.1) guaranteed to accept exactly one value. The effect of pass-
are anticipated by this report, and implementations must ing some other number of values to such a continuation is
raise an exception of the appropriate condition type if they unspecified. The call-with-values procedure described
encounter such a situation. in section 9.18 makes it possible to create continuations
Implementation restrictions not explicitly covered in this that accept specified numbers of return values. If the num-
report are of course discouraged, but implementations are ber of return values passed to a continuation created by a
required to report violations of implementation restric- call to call-with-values is not accepted by its consumer
tions. For example, an implementation may raise an excep- that was passed in that call, then an exception is raised.
tion with condition type &implementation-restriction A number of forms in the base library have sequences of ex-
if it does not have enough storage to run a program. pressions as subforms that are evaluated sequentially, with
The above requirements for violations and implementation the return values of all but the last expression being dis-
restrictions apply only in scripts and libraries that are said carded. The continuations discarding these values accept
to be safe. In unsafe code, implementations might not raise any number of values.
the exceptions that are normally raised in those situations.
The distinction between safe and unsafe code is explained
in section 4.4. 4.6. Storage model
indicates that the built-in procedure vector-ref takes two &who condition type
arguments, a vector vector and an exact non-negative in-
teger k (see below). The header lines
indicates that &who is a condition type.
(make-vector k ) procedure
(make-vector k fill ) procedure The description of an entry occasionally states that it is
the same as another entry. This means that both entries
indicate that the make-vector procedure takes either are equivalent. Specifically, it means that if both entries
one or two arguments. The parameter names are case- have the same name and are thus exported from different
insensitive: Vector is the same as vector . libraries, the entries from both libraries can be imported
An operation that is presented with an argument that it under the same name without conflict.
is not specified to handle raises an exception with condi-
tion type &contract. Also, if the number of arguments
presented to an operation does not match any specified 5.2. List arguments
count, an exception with condition type &contract must
be raised. List arguments are immutable in programs that do not
For succinctness, we follow the convention that if a param- make use of the (r6rs mutable-pairs) library. In such
eter name is also the name of a type, then the correspond- programs, a procedure accepting a list as an argument can
ing argument must be of the named type. For example, check whether the argument is a list by traversing it.
the header line for vector-ref given above dictates that In programs that mutate pairs through use of the (r6rs
the first argument to vector-ref must be a vector. The mutable-pairs) library, a pair that is the head of a list at
following naming conventions imply type restrictions: one moment may not always be the head of a list. Thus
obj any object a traversal of the structure cannot by itself guarantee that
z complex number the structure is a list; one must also know that no con-
x real number current or interleaved computation can mutate the pairs of
y real number the structure. This greatly complicates the description of
q rational number how certain procedures must verify that their arguments
n integer are valid.
k exact non-negative integer For that reason, the specifications of procedures that ac-
octet exact integer in {0, . . . , 255} cept lists generally assume that those lists are not mutated.
bytes exact integer in {-128, . . . , 127} Section 23.2 relaxes that assumption and states more pre-
char character (see section 9.14) cise restrictions on the arguments to these procedures.
pair pair (see section 9.12)
list list (see section 5.2)
vector vector (see section 9.16) 5.3. Evaluation examples
string string (see section 9.15)
condition condition (see section 14.2)
The symbol “=⇒” used in program examples should be
bytes bytes object (see chapter 11)
read “evaluates to.” For example,
proc procedure (see section 1.5)
(* 5 8) =⇒ 40
Other type restrictions are expressed through parameter
naming conventions that are described in specific chapters. means that the expression (* 5 8) evaluates to the ob-
For example, chapter 16 uses a number of special parameter ject 40. Or, more precisely: the expression given by the
variables for the various subsets of the numbers. sequence of characters “(* 5 8)” evaluates, in the initial
Descriptions of procedures may express other restrictions environment, to an object that may be represented exter-
on the arguments of a procedure. Typically, such a restric- nally by the sequence of characters “40”. See section 3.3
tion is formulated as a phrase of the form “x must be a for a discussion of external representations of objects.
. . . ” (or otherwise using the word “must.”) As with im- The “=⇒” symbol is also used when the evaluation of an
plicit restrictions, such a phrase means that an exception expression raises an exception. For example,
with condition type &contract is raised if the argument
does not meet the restriction. (integer->char #xD800) =⇒ &contract exception
5.4. Unspecified behavior By convention, the names of procedures that store values
into previously allocated locations (see section 4.6) usually
If the value of an expression is said to be “unspecified,” end in “!”. Such procedures are called mutation proce-
then the expression must evaluate without raising an ex- dures. By convention, the value returned by a mutation
ception, but the values returned depends on the imple- procedure is the unspecified value (see section 9.8), but
mentation; this report explicitly does not say what values this convention is not always followed.
should be returned. By convention, “->” appears within the names of proce-
Some expressions are specified to return the unspecified dures that take an object of one type and return an anal-
value, which is a special value returned by the unspecified ogous object of another type. For example, list->vector
procedure. (See section 9.8.) In this case, the return value takes a list and returns a vector whose elements are the
is meaningless, and programmers are discouraged from re- same as those of the list.
lying on its specific nature.
so that there is no ambiguity about whether a library effects. The exported bindings may be defined within the
needs to be executed for another library’s compile time library or imported into the library.
and/or run time. An identifier can be imported from two or more libraries
• Namespace management, so that different library pro- or for two phases from the same library only if the bind-
ducers are unlikely to define the same top-level name. ing exported by each library is the same (i.e., the binding
is defined in one library, and it arrives through the im-
ports only by exporting and re-exporting). Otherwise, no
It does not address the following: identifier can be imported multiple times, defined multi-
ple times, or both defined and imported. No identifiers are
• Mutually dependent libraries. visible within a library except for those explicitly imported
into the library or defined within the library.
• Separation of library interface from library implemen-
tation. A hlibrary namei must be one of the following:
hidentifieri
• Code outside of a library (e.g., 5 by itself as a pro-
(hidentifier1 i hidentifier2 i ... hversioni)
gram).
where hversioni is empty or has the following form:
• Local modules and local imports.
(hsubversion1 i hsubversion2 i ...)
Each hsubversioni must be an exact nonnegative integer.
6.1. Library form
As a hlibrary namei, hidentifieri is shorthand for
(hidentifieri).
A library declaration contains the following elements:
Each himport speci specifies a set of bindings to be im-
ported into the library, the phases in which they are to
• a name for the library (possibly compound, with ver- be available, and the local names by which they are to be
sioning), known. A himport speci must be one of the following:
• a list of exports, which name a subset of the bindings himport seti
defined within or imported into the library, (for himport seti himport phasei ...)
An himport phasei is one of the following:
• a list of import dependencies, where each dependency
run
specifies:
expand
– the imported library’s name, (meta hleveli)
– the relevant phases, e.g., expand or run time, and where hleveli is an exact nonnegative integer.
– the subset of the library’s exports to make avail- As an himport phasei, run is an abbreviation for (meta
able within the importing library, and the local 0), and expand is an abbreviation for (meta 1). Phases
names to use within the importing library for are discussed in section 6.2.
each of the library’s exports, and An himport seti names a set of bindings from another li-
brary, and possibly specifies local names for the imported
• a library body, consisting of a sequence of definitions
bindings. It must be one of the following:
preceded by a sequence of declarations and followed
by a sequence of expressions. hlibrary referencei
(only himport seti hidentifieri ...)
(except himport seti hidentifieri ...)
A library definition must have the following form:
(add-prefix himport seti hidentifieri)
(library hlibrary namei (rename himport seti (hidentifieri hidentifieri) ...)
(export hexport speci ...)
(import himport speci ...)
A hlibrary referencei identifies a library by its (possibly
hlibrary bodyi) compound) name and optionally by its version. It must
have one the following forms:
The hlibrary namei specifies the name of the library,
hidentifieri
the export form specifies the exported bindings, and
(hidentifier1 i hidentifier2 i ... hversion referencei)
the import form specifies the imported bindings. The
hlibrary bodyi specifies the set of definitions, both for local hIdentifieri is shorthand for (hidentifieri). A
(unexported) and exported bindings, and the set of initial- hversion referencei must have one of the following
ization expressions (commands) to be evaluated for their forms:
22 Revised5.91 Scheme
where a hsubversion conditioni must have one of these In an hexport speci, an hidentifieri names a single bind-
forms: ing defined within or imported into the library, where the
(>= hsubversioni) external name for the export is the same as the name of
(<= hsubversioni) the binding within the library. A rename spec exports the
(and hsubversion condition1 i hsubversion condition2 i ...) binding named by the first hidentifieri in each pair, using
(or hsubversion condition1 i hsubversion condition2 i ...) the second hidentifieri as the external name.
(not hsubversion conditioni)
The hlibrary bodyi of a library form consists of forms
The sequence of identifiers in the importing library’s that are classified into declarations, definitions, and ex-
hlibrary referencei must match the sequence of identifiers pressions. Which forms belong to which class depends
in the imported library’s hlibrary namei. The importing on the imported libraries and the result of expansion—
library’s hversion referencei specifies a predicate on a pre- see chapter 8. Generally, forms that are not declarations
fix of the imported library’s hversioni. Each integer must (see section 9.22 for declarations available through the base
match exactly and each condition has the expected mean- library) or definitions (see section 9.2 for definitions avail-
ing. Everything beyond the prefix specified in the version able through the base library) are expressions.
reference matches unconditionally. When more than one
library is identified by a library reference, the choice of li- A hlibrary bodyi is like a hbodyi (see section 9.4) except
braries is determined in some implementation-dependent that hlibrary bodyis need not include any expressions. It
manner. must have the following form:
To avoid problems such as incompatible types and repli- hdeclarationi ... hdefinitioni ... hexpressioni ...
cated state, two libraries whose library names contain the
When base-library begin forms occur in a library body
same sequence of identifiers but whose versions do not
prior to the first expression, they are spliced into the body;
match cannot co-exist in the same program.
see section 9.5.7. Some or all of the library body, including
By default, all of an imported library’s exported bind- portions wrapped in begin forms, may be specified by a
ings are made visible within an importing library using syntactic abstraction (see section 6.3.2).
the names given to the bindings by the imported library.
The precise set of bindings to be imported and the names The transformer expressions and transformer bindings are
of those bindings can be adjusted with the only, except, created from left to right, as described in chapter 8. The
add-prefix, and rename forms as described below. variable-definition right-hand-side expressions are evalu-
ated from left to right, as if in an implicit letrec*, and
• The only form produces a subset of the bindings the body expressions are also evaluated from left to right
from another himport seti, including only the listed after the variable-definition right-hand-side expressions. A
hidentifieris; if any of the included hidentifieris is not fresh location is created for each exported variable and ini-
in himport seti, an exception is raised. tialized to the value of its local counterpart. The effect of
returning twice to the continuation of the last body expres-
• The except form produces a subset of the bindings sion is unspecified.
from another himport seti, including all but the listed
hidentifieris; if any of the excluded hidentifieris is not The names library, export, import, for, run, expand,
in himport seti, an exception is raised. meta, import, export, only, except, and rename appear-
ing in the library syntax are part of the syntax and are
• The add-prefix adds the hidentifieri prefix to each not reserved, i.e, the same can be used for other purposes
name from another himport seti. within the library or even exported from or imported into
a library with different meanings, without affecting their
• The rename form, for each pair of identifiers
use in the library form.
(hidentifieri hidentifieri), removes a binding from the
set from himport seti, and adds it back with a different In the case of any ambiguities that arise from the use of
name. The first identifier is the original name, and the one of these names as a shorthand (single-identifier) li-
second identifier is the new name. If the original name brary name, the ambiguity should be resolved in favor
is not in himport seti, or if the new name is already in of the interpretation of the name as library syntax. For
himport seti, an exception is raised. example, (import (for lib expand)) should be taken
6. Libraries 23
as importing library lib for expand, not as importing The effective import phases of an imported binding are
a library named (for lib expand). The user can al- determined by the enclosing for form, if any, in the
ways eliminate such ambiguities by avoiding the shorthand import form of the importing library, in addition to
hlibrary referencei syntax when such an ambiguity might the phase of the identifier in the exporting library. An
arise. himport seti without an enclosing for is equivalent to (for
himport seti run). Import and export phases are com-
Bindings defined with a library are not visible in code out-
bined by pairwise addition of all phase combinations. For
side of the library, unless the bindings are explicitly ex-
example, references to an imported identifier exported for
ported from the library. An exported macro may, however,
phases pa and pb and imported for phases qa , qb , and qc
implicitly export an otherwise unexported identifier defined
are valid at phases pa + qq , pa + qb , pa + qc , pb + qq , pb + qb ,
within or imported into the library. That is, it may insert a
and pb + qc .
reference to that identifier into the output code it produces.
The export phase of an exported binding is run for all
All explicitly exported variables are immutable in both the bindings that are defined within the exporting library. The
exporting and importing libraries. An exception with con- export phases of a reexported binding, i.e., an export im-
dition type &syntax is thus raised if an explicitly exported ported from another library, are the same as the effective
variable appears on the left-hand side of a set! expres- import phases of that binding within the reexporting li-
sion, either in the exporting or importing libraries. All brary.
other variables defined within a library are mutable.
The export phase of all bindings exported by the libraries
All implicitly exported variables are also immutable in both defined in this report, except for the composite r6rs library
the exporting and importing libraries. An exception with (see chapter 21), is run, while the export phases for all
condition type &syntax is thus raised if a variable appears bindings exported by r6rs are run and expand.
on the left-hand side of a set! expression in any code pro-
Rationale: The r6rs library is intended as a convenient import
duced by an exported macro outside of the library in which
for libraries where fine control over imported bindings is not
the variable is defined. An exception with condition type
necessary or desirable. The r6rs library exports all bindings
&syntax is also raised if a reference to an assigned variable
for expand as well as run so that it is convenient for writing
appears in any code produced by an exported macro out-
macros as well as run-time code.
side of the library in which the variable is defined, where
an assigned variable is one that appears on the left-hand The effective import phases implicitly determine when in-
side of a set! expression in the exporting library. formation about a library must be available and also when
the various forms contained within a library must be eval-
Note: The asymmetry in the exception-raising requirements
uated.
for attempts to assign explicitly and implicitly exported vari-
ables reflects the fact that the error can be determined for im- Every library can be characterized by expand-time infor-
plicitly exported variables only when the importing library is mation (minimally, its imported libraries, a list of the ex-
expanded. ported keywords, a list of the exported variables, and code
to evaluate the transformer expressions) and run-time in-
formation (minimally, code to evaluate the variable def-
6.2. Import and export phases inition right-hand-side expressions, and code to evaluate
the body expressions). The expand-time information must
be available to expand references to any exported binding,
All bindings imported via a library’s import form are vis- and the run-time information must be available to evaluate
ible throughout the library’s hlibrary bodyi. An exception references to any exported variable binding.
may be raised, however, if a binding is used out of its de-
clared phase(s): If any of a library’s bindings are imported by another li-
brary “for expand” (or for any meta level greater than 0),
both expand-time and run-time information for the first
• Bindings used in run-time code must be imported “for library is made available when the second library is ex-
run,” which is equivalent to “for (meta 0).” panded. If any of a library’s bindings are imported by
another library “for run,” the expand-time information for
• Bindings used in the body of a transformer (appearing
the first library is made available when the second library
on the right-hand-side of a transformer binding) in
is expanded, and the run-time information for the first li-
run-time code must be imported “for expand,” which
brary is made available when the run-time information for
is equivalent to “for (meta 1),”
the second library is made available.
• Bindings used in the body of a transformer appear- It is also relevant when the code to evaluate a library’s
ing within the body of a transformer in run-time code transformer expressions is executed and when the code
must be imported “for (meta 2),” and so on. to evaluate the library’s variable-definition right-hand-side
24 Revised5.91 Scheme
• Invoke at phase N any library that is imported by this An expression consisting of a variable (section 4.2) is a
library “for run” and that is not yet invoked at phase variable reference. The value of the variable reference is
N. the value stored in the location to which the variable is
bound. It is a syntax violation to reference an unbound
• Evaluate the library’s variable-definition right-hand- variable.
side and body expressions. ; these examples assume the base library
; has been imported
The order in which imported libraries are invoked is not (define x 28)
defined, but imported libraries must be invoked before the x =⇒ 28
library’s variable-definition right-hand-side and body ex-
pressions are evaluated. Procedure calls
An implementation is allowed to distinguish visits of a li-
brary across different phases or to treat a visit at any phase (hoperatori hoperand1 i . . . ) syntax
as a visit at all phases. Similarly, an implementation is al- A procedure call is written by simply enclosing in paren-
lowed to distinguish invocations of a library across different theses expressions for the procedure to be called and the
phases or to treat an invocation at any phase as an invo- arguments to be passed to it. A form in an expression
cation at all phases. An implementation is further allowed context is a procedure call if hoperatori is not an identifier
to start each expansion of a library form by removing all bound as a syntactic keyword.
library bindings above phase 0. Thus, a portable library’s When an procedure call is evaluated, the operator and
meaning must not depend on whether the invocations are operand expressions are evaluated (in an unspecified or-
distinguished or preserved across phases or library expan- der) and the resulting procedure is passed the resulting
sions. arguments..
6. Libraries 25
; these examples assume the base library Keywords occupy the same name space as variables. That
; has been imported is, within the same scope, an identifier can be bound as
(+ 3 4) =⇒ 7 a variable or keyword, or neither, but not both, and local
((if #f + *) 3 4) =⇒ 12 bindings of either kind may shadow other bindings of either
If the value of hoperatori is not a procedure, an exception kind.
with condition type &contract is raised. Macros defined using syntax-rules are “hygienic” and
Note: In contrast to other dialects of Lisp, the order of “referentially transparent” and thus preserve Scheme’s lex-
evaluation is unspecified, and the operator expression and the ical scoping [31, 32, 3, 10, 14]:
operand expressions are always evaluated with the same evalu-
ation rules. • If a macro transformer inserts a binding for an iden-
Note: Although the order of evaluation is otherwise unspeci- tifier (variable or keyword), the identifier is in effect
fied, the effect of any concurrent evaluation of the operator and renamed throughout its scope to avoid conflicts with
operand expressions is constrained to be consistent with some other identifiers.
sequential order of evaluation. The order of evaluation may be • If a macro transformer inserts a free reference to an
chosen differently for each procedure call. identifier, the reference refers to the binding that was
Note: In many dialects of Lisp, the form () is a legitimate visible where the transformer was specified, regardless
expression. In Scheme, expressions written as list/pair forms of any local bindings that may surround the use of the
must have at least one subexpression, so () is not a syntactically macro.
valid expression.
Macros defined using the syntax-case facility are also hy-
gienic unless datum->syntax (see section 17.6) is used.
6.3.2. Macros
which do not support the Unix-like script header syntax 8. Expansion process
may need to use other mechanisms, such as a registered
Macro uses (see section 6.3.2) are expanded into core forms
filename extension, in order to associate a script with the
at the start of evaluation (before compilation or inter-
scheme-script executable.
pretation) by a syntax expander. (The set of core forms
is implementation-dependent, as is the representation of
7.1.2. Script substance these forms in the expander’s output.) If the expander en-
counters a syntactic abstraction, it invokes the associated
The rules for hscript substancei specify syntax at the form transformer to expand the syntactic abstraction, then re-
level. peats the expansion process for the form returned by the
transformer. If the expander encounters a core form, it re-
The himport formi is identical to the import clause in li- cursively processes the subforms, if any, and reconstructs
braries (see section 6.1), and specifies a set of libraries to the form from the expanded subforms. Information about
import. A hscript bodyi is like a hlibrary bodyi (see sec- identifier bindings is maintained during expansion to en-
tion 6.1), except that declarations, definitions and expres- force lexical scoping for variables and keywords.
sions may occur in any order, and that the final form of
the script body must be an expression. Thus, the syntax To handle internal definitions, the expander processes the
specified by hscript body formi refers to the result of macro initial forms in a hbodyi (see section 9.4) or hlibrary bodyi
expansion. (see section 6.1) from left to right. How the expander pro-
cesses each form encountered as it does so depends upon
When base-library begin forms occur anywhere within the kind of form.
a script body, they are spliced into the body; see sec-
tion 9.5.7. Some or all of the script body, including portions
wrapped in begin forms, may be specified by a syntactic macro use The expander invokes the associated trans-
abstraction (see section 6.3.2). former to transform the macro use, then recursively
performs whichever of these actions are appropriate
for the resulting form.
7.2. Script semantics
declaration form If none of the body forms processed so
far is a definition, the declaration is handled in some
A script is executed by treating the script similarly to implementation-dependent fashion. It is a syntax vio-
a library, and invoking it. The semantics of a script lation for a declaration to appear after a definition.
body may be roughly explained by a simple translation
into a library body: All declarations at the script top define-syntax form The expander expands and evalu-
level are moved to the front, and each hexpressioni that ates the right-hand-side expression and binds the key-
appears before a variable definition in the script body word to the resulting transformer.
is converted into a dummy definition (define hvariablei
hexpressioni), where hvariablei is fresh identifier. (It is define form The expander records the fact that the de-
generally impossible to determine which forms are decla- fined identifier is a variable but defers expansion of the
rations, definitions, and expressions without concurrently right-hand-side expression until after all of the defini-
expanding the body, so the actual translation is somewhat tions have been processed.
more complicated; see chapter 8.)
A script may access its command-line arguments by call- begin form The expander splices the subforms into the
ing the command-line-arguments procedure (see sec- list of body forms it is processing. (See section 9.5.7.)
tion 20.4). The final expression of a script must return an
let-syntax or letrec-syntax form The expander
exact integer, which becomes the exit value of the script.
splices the inner body forms into the list of (outer)
How that exit value is communicated to the environment
body forms it is processing, arranging for the key-
is implementation-specific. When a script is invoked as a
words bound by the let-syntax and letrec-syntax
Unix or Windows program, the exit value simply becomes
to be visible only in the inner body forms.
the exit status of the program.
If an exception with a &serious condition is raised dur- expression, i.e., nondefinition The expander com-
ing the execution of the script, the default exception pletes the expansion of the deferred right-hand-side
handler behaves as described in section 14.1, and an forms and the current and remaining expressions in
implementation-specific exit value is communicated to the the body, then constructs a residual letrec* form
environment. On Unix, this value is according to the defi- from the defined variables, expanded right-hand-side
nition of EX SOFTWARE in the sysexits.h header [24]. expressions, and expanded body expressions.
28 Revised5.91 Scheme
It is a syntax violation if the keyword that identifies one of odd? appearing in these expressions are expanded using
of the body forms as a definition (derived or core) is re- the transformer associated with the keyword odd?. The
defined by the same definition or a later definition in the final output is the equivalent of
same body. To detect this error, the expander records the
(lambda (x)
identifying keyword for each macro use, define-syntax (letrec* ([even?
form, define form, begin form, let-syntax form, and (lambda (n)
letrec-syntax form it encounters while processing the (or (= n 0)
definitions and checks each newly defined identifier (define (not (even? (- n 1)))))])
or define-syntax left-hand side) against the recorded key- (not (even? (if (not (even? x)) (* x x) x)))))
words, as with bound-identifier=? (section 17.5). For
example, the following forms are syntax violations.
although the structure of the output is implementation de-
(let () pendent.
(define define 17)
Because definitions and expressions can be interleaved in a
define)
hscript bodyi (see chapter 7), the expander’s processing of
(let-syntax ([def0 (syntax-rules () a hscript bodyi is somewhat more complicated. It behaves
[( x) (define x 0)])]) as described above for a hbodyi or hlibrary bodyi with the
(let () following exceptions. First, it treats declarations that ap-
(def0 z) pear after any definitions or expressions as if they appeared
(define def0 ’(def 0)) before all of the definitions and expressions. Second, when
(list z def0))) the expander finds a nondefinition, it defers its expansion
and continues scanning for definitions. Once it reaches the
Expansion of each variable definition right-hand side is de- end of set of forms, it processes the deferred right-hand-side
ferred until after all of the definitions have been seen so and body expressions, then constructs a residual letrec*
that each keyword and variable reference within the right- form from the defined variables, expanded right-hand-side
hand side resolves to the local binding, if any. expressions, and expanded body expressions. For each
body expression that appears before a variable definition in
Note that this algorithm does not directly reprocess any the body, a dummy binding is created at the corresponding
form. It requires a single left-to-right pass over the defini- place within the set of letrec* bindings, with a fresh tem-
tions followed by a single pass (in any order) over the body porary variable on the left-hand side and the expression on
expressions and deferred right-hand sides. the right-hand side, so that left-to-right evaluation order is
For example, in preserved.
(lambda (x)
(define-syntax defun 9. Base library
(syntax-rules () This chapter describes Scheme’s base library, which ex-
[( (x . a) e) (define x (lambda a e))]))
ports many of the procedure and syntax bindings that are
(defun (even? n) (or (= n 0) (odd? (- n 1))))
traditionally associated with Scheme.
(define-syntax odd?
(syntax-rules () [( n) (not (even? n))])) Section 9.23 defines the rules that identify tail calls and
(odd? (if (odd? x) (* x x) x))) tail contexts in base-library constructs.
The definition of defun is encountered first, and the key- 9.1. Base types
word defun is associated with the transformer resulting
from the expansion and evaluation of the corresponding
No object satisfies more than one of the following predi-
right-hand side. A use of defun is encountered next and
cates:
expands into a define form. Expansion of the right-hand
side of this define form is deferred. The definition of odd? boolean? pair?
is next and results in the association of the keyword odd? symbol? number?
with the transformer resulting from expanding and eval- char? string?
uating the corresponding right-hand side. A use of odd? vector? procedure?
unspecified? eof-object?
appears next and is expanded; the resulting call to not
null?
is recognized as an expression because not is bound as a
variable. At this point, the expander completes the ex- These predicates define the base types boolean, pair, sym-
pansion of the current expression (the not call) and the bol, number, char (or character), string, vector, and pro-
deferred right-hand side of the even? definition; the uses cedure. Moreover, the empty list is a special object of its
9. Base library 29
own type, as are the unspecified value, and the end of file 9.3. Syntax definitions
oject.
Although there is a separate boolean type, any Scheme Syntax definitions are established with define-syntax. A
value can be used as a boolean value for the purpose of a define-syntax form is a hdefinitioni and may appear any-
conditional test. As explained in section 9.11, all values where other definitions may appear.
count as true in such a test except for #f. This report uses
the word “true” to refer to any Scheme value except #f, (define-syntax hvariablei htransformer speci) syntax
and the word “false” to refer to #f.
This binds the keyword hvariablei to a transformer speci-
fication specified by htransformer speci, which must either
be a syntax-rules form (see section 9.21), or evaluate, at
9.2. Definitions macro-expansion time, to a transformer. (Section 17.3).
Keyword bindings established by define-syntax are vis-
The define forms described in this section are definitions ible throughout the body in which they appear, except
for value bindings and may appear anywhere other defini- where shadowed by other bindings, and nowhere else, just
tions may appear. See section 6.1. like variable bindings established by define. All bindings
A hdefinitioni must have one of the following forms: established by a set of internal definitions, whether key-
word or variable definitions, are visible within the defini-
tions themselves. For example:
• (define hvariablei hexpressioni) This binds
hvariablei to a new location before assigning the (let ()
value of hexpressioni to it. (define even?
(lambda (x)
(or (= x 0) (odd? (- x 1)))))
(define add3 (define-syntax odd?
(lambda (x) (+ x 3))) (syntax-rules ()
(add3 3) =⇒ 6 ((odd? x) (not (even? x)))))
(define first car) (even? 10)) =⇒ #t
(first ’(1 2)) =⇒ 1
An implication of the left-to-right processing order (sec-
• (define hvariablei) tion 8) is that one internal definition can affect whether
a subsequent form is also a definition. For example, the
This form is equivalent to expression
(define hvariablei
(lambda (hformalsi) hbodyi)). 9.4. Bodies and sequences
• (define (hvariablei . hformali) hbodyi) The body hbodyi of a lambda, let, let*, let-values,
hFormali must be a single variable. This form is equiv- let*-values, letrec*, letrec expression or that of a def-
alent to inition with a body has the following form:
hdeclarationi ...hdefinitioni ...hsequencei
(define hvariablei
(lambda hformali hbodyi)).
hDeclarationi is according to section 9.22.
hSequencei has the following form:
• A syntax definition, see section 9.3. hexpression1 i hexpression2 i ...
30 Revised5.91 Scheme
((lambda (x)
The entries in this section describe the expressions of the (define (p y)
base language, which may occur in the position of the (+ y 1))
hexpressioni syntactic variable. The expressions also in- (+ (p x) x))
clude constant literals, variable references and procedure 5) =⇒ 11
calls as described in section 6.3.1.
(define reverse-subtract
(lambda (x y) (- y x)))
9.5.1. Literal expressions (reverse-subtract 7 10) =⇒ 3
the datum denoted by each hdatumi. If the result of eval- (or (= 2 2) (> 2 1)) =⇒ #t
uating hkeyi is equivalent (in the sense of eqv?; see sec- (or (= 2 2) (< 2 1)) =⇒ #t
tion 9.6) to a datum, then the expressions in the corre- (or #f #f #f) =⇒ #f
sponding hclausei are evaluated from left to right and the (or ’(b c) (/ 3 0)) =⇒ (b c)
result(s) of the last expression in the hclausei is(are) re- The or keyword could be defined in terms of if using
turned as the result(s) of the case expression. If the result syntax-rules (see section 9.21) as follows:
of evaluating hkeyi is different from every datum, then if
there is an else clause its expressions are evaluated and the (define-syntax or
result(s) of the last is(are) the result(s) of the case ex- (syntax-rules ()
pression; otherwise the result of the case expression is the ((or) #f)
unspecified value. ((or test) test)
((or test1 test2 ...)
(case (* 2 3) (let ((x test1))
((2 3 5 7) ’prime) (if x x (or test2 ...))))))
((1 4 6 8 9) ’composite)) =⇒ composite
(case (car ’(c d))
((a) ’a) 9.5.6. Binding constructs
((b) ’b)) =⇒ the unspecified value
(case (car ’(c d)) The four binding constructs let, let*, letrec*, and
((a e i o u) ’vowel) letrec give Scheme a block structure, like Algol 60. The
((w y) ’semivowel) syntax of the four constructs is identical, but they differ in
(else ’consonant)) =⇒ consonant the regions they establish for their variable bindings. In a
A sample definition of case in terms of simpler forms is in let expression, the initial values are computed before any
appendix B. of the variables become bound; in a let* expression, the
bindings and evaluations are performed sequentially; while
in a letrec* and in a letrec expression, all the bindings
(and htest1 i . . . ) syntax
are in effect while their initial values are being computed,
Syntax: The htestis must be expressions. Semantics: The thus allowing mutually recursive definitions.
htesti expressions are evaluated from left to right, and the
value of the first expression that evaluates to a false value In addition, the binding constructs let-values and
(see section 9.11) is returned. Any remaining expressions let*-values allow the binding of results of expression re-
are not evaluated. If all the expressions evaluate to true turning multiple values. They are analogous to let and
values, the value of the last expression is returned. If there let* in the way they establish regions: in a let-values
are no expressions then #t is returned. expression, the initial values are computed before any of
the variables become bound; in a let*-values expression,
(and (= 2 2) (> 2 1)) =⇒ #t the bindings are performed sequentially.
(and (= 2 2) (< 2 1)) =⇒ #f
(and 1 2 ’c ’(f g)) =⇒ (f g) Note: These forms are compatible with SRFI 11 [25].
(and) =⇒ #t
The and keyword could be defined in terms of if using (let hbindingsi hbodyi) syntax
syntax-rules (see section 9.21) as follows: Syntax: hBindingsi must have the form
(define-syntax and ((hvariable1 i hinit1 i) . . . ),
(syntax-rules ()
((and) #t) where each hiniti is an expression, and hbodyi is as de-
((and test) test) scribed in section 9.4. It is a syntax violation for a
((and test1 test2 ...) hvariablei to appear more than once in the list of variables
(if test1 (and test2 ...) #f)))) being bound.
Semantics: The hinitis are evaluated in the current envi-
(or htest1 i . . . ) syntax ronment (in some unspecified order), the hvariableis are
Syntax: The htestis must be expressions. Semantics: The bound to fresh locations holding the results, the hbodyi is
htesti expressions are evaluated from left to right, and the evaluated in the extended environment, and the value(s) of
value of the first expression that evaluates to a true value the last expression of hbodyi is(are) returned. Each bind-
(see section 9.11) is returned. Any remaining expressions ing of a hvariablei has hbodyi as its region.
are not evaluated. If all expressions evaluate to false values, (let ((x 2) (y 3))
the value of the last expression is returned. If there are no (* x y)) =⇒ 6
expressions then #f is returned.
9. Base library 33
hvariablei of any of the bindings that follow it in hbindingsi. A sample definition of let-values in terms of simpler
If this restriction is violated, an exception with condition forms is in appendix B.
type &contract is raised. The restriction is necessary be-
cause Scheme passes arguments by value rather than by (let*-values hmv-bindingsi hbodyi) syntax
name.
The let*-values form is the same as with let-values,
The letrec* keyword could be defined approximately but the bindings are processed sequentially from left
in terms of let and set! using syntax-rules (see sec- to right, and the region of the bindings indicated by
tion 9.21) as follows: (hformalsi hiniti) is that part of the let*-values expres-
sion to the right of the bindings. Thus, the second set of
(define-syntax letrec*
(syntax-rules ()
bindings is evaluated in an environment in which the first
((letrec* ((var1 init1) ...) body1 body2 ...) set of bindings is visible, and so on.
(let ((var1 <undefined>) ...) (let ((a ’a) (b ’b) (x ’x) (y ’y))
(set! var1 init1) (let*-values (((a b) (values x y))
... ((x y) (values a b)))
(let () body1 body2 ...))))) (list a b x y))) =⇒ (x y x y)
The syntax <undefined> represents an expression that re- The following macro defines let*-values in terms of let
turns something that, when stored in a location, causes an and let-values:
exception with condition type &contract to be raised if an (define-syntax let*-values
attempt to read from or write to the location occurs before (syntax-rules ()
the assignments generated by the letrec* transformation ((let*-values () body1 body2 ...)
take place. (No such expression is defined in Scheme.) (let () body1 body2 ...))
((let*-values (binding1 binding2 ...)
body1 body2 ...)
(let-values hmv-bindingsi hbodyi) syntax (let-values (binding1)
(let*-values (binding2 ...)
Syntax: hMv-bindingsi must have the form body1 body2 ...)))))
((hformals1 i hinit1 i) . . . ),
numbers in constant time, whereas eq? implemented as pointer Note: The unspecified value is not a datum value, and thus
comparison will always finish in constant time. The eq? predi- has no external representation.
cate may be used like eqv? in applications using procedures to
implement objects with state since it obeys the same constraints
(unspecified? obj ) procedure
as eqv?.
Returns #t if obj is the unspecified value, otherwise returns
#f.
(equal? obj1 obj2 ) procedure
The equal? predicate returns #t if and only if the (possibly
infinite) unfoldings of its arguments into regular trees are 9.9. End of file object
equal as ordered trees.
The end of file object is returned by various I/O procedures
The equal? predicate treats pairs and vectors as nodes (see section 15.3) when they reach end of file.
with outgoing edges, uses string=? to compare strings,
uses bytes=? to compare bytes objects (see chapter 11),
and uses eqv? to compare other nodes. (eof-object) procedure
Note: The behavior of these type predicates on inexact num- (real->single x ) procedure
bers is unreliable, because any inaccuracy may affect the result. (real->double x ) procedure
Given a real number x , these procedures compute the best
IEEE-754 single or double precision approximation to x
and return that approximation as an inexact real.
(exact? z ) procedure
(inexact? z ) procedure Note: Both of the two conversions performed by these pro-
cedures (to IEEE-754 single or double, and then to an inexact
These numerical predicates provide tests for the exactness real) may lose precision, introduce error, or may underflow or
of a quantity. For any Scheme number, precisely one of overflow.
these predicates is true.
Rationale: The ability to round to IEEE-754 single or double
(exact? 5) =⇒ #t precision is occasionally needed for control of precision or for
(inexact? +inf.0) =⇒ #t interoperability.
Arithmetic operations
Generic conversions
(= z1 z2 z3 . . . ) procedure
(->inexact z ) procedure (< x1 x2 x3 . . . ) procedure
(->exact z ) procedure (> x1 x2 x3 . . . ) procedure
(<= x1 x2 x3 . . . ) procedure
->inexact returns an inexact representation of z . If in-
(>= x1 x2 x3 . . . ) procedure
exact numbers of the appropriate type have bounded pre-
cision, then the value returned is an inexact number that These procedures return #t if their arguments are (respec-
is nearest to the argument. If an exact argument has no tively): equal, monotonically increasing, monotonically de-
reasonably close inexact equivalent, an exception with con- creasing, monotonically nondecreasing, or monotonically
dition type &implementation-violation may be raised. nonincreasing #f otherwise.
->exact returns an exact representation of z . The value (= +inf.0 +inf.0) =⇒ #t
returned is the exact number that is numerically closest to (= -inf.0 +inf.0) =⇒ #f
the argument; in most cases, the result of this procedure (= -inf.0 -inf.0) =⇒ #t
should be numerically equal to its argument. If an inexact For any real number x that is neither infinite nor NaN:
argument has no reasonably close exact equivalent, an ex-
ception with condition type &implementation-violation (< -inf.0 x +inf.0)) =⇒ #t
may be raised. (> +inf.0 x -inf.0)) =⇒ #t
These procedures implement the natural one-to-one corre- These predicates are required to be transitive.
spondence between exact and inexact integers throughout Note: The traditional implementations of these predicates in
an implementation-dependent range. Lisp-like languages are not transitive.
->inexact and ->exact are idempotent. Note: While it is possible to compare inexact numbers using
these predicates, the results may be unreliable because a small
inaccuracy may affect the result; this is especially true of = and
(real->flonum x ) procedure zero?.
(rationalize x1 x2 ) procedure
(numerator q) procedure The rationalize procedure returns the simplest rational
(denominator q) procedure number differing from x1 by no more than x2 . A rational
These procedures return the numerator or denominator of number r1 is simpler than another rational number r2 if
their argument; the result is computed as if the argument r1 = p1 /q1 and r2 = p2 /q2 (in lowest terms) and |p1 | ≤ |p2 |
was represented as a fraction in lowest terms. The denom- and |q1 | ≤ |q2 |. Thus 3/5 is simpler than 4/7. Although not
inator is always positive. The denominator of 0 is defined all rationals are comparable in this ordering (consider 2/7
to be 1. and 3/5) any interval contains a rational number that is
simpler than every other rational number in that interval
(numerator (/ 6 4)) =⇒ 3 (the simpler 2/5 lies between 2/7 and 3/5). Note that
(denominator (/ 6 4)) =⇒ 2 0 = 0/1 is the simplest rational of all.
(denominator
(->inexact (/ 6 4))) =⇒ 2.0 (rationalize
(->exact .3) 1/10) =⇒ 1/3 ; exact
(rationalize .3 1/10) =⇒ #i1/3 ; inexact
(floor x ) procedure
(ceiling x ) procedure (rationalize +inf.0 3) =⇒ +inf.0
(truncate x ) procedure (rationalize +inf.0 +inf.0) =⇒ +nan.0
(round x ) procedure (rationalize 3 +inf.0) =⇒ 0.0
Numerical Input and Output valid notation for a number, then string->number returns
#f.
(list-ref l k ) procedure Symbols are objects whose usefulness rests on the fact that
two symbols are identical (in the sense of eq?, eqv? and
L must be a chain of pairs of size at least k + 1.
equal?) if and only if their names are spelled the same way.
Returns the k th element of l . This is exactly the property needed to represent identifiers
(list-ref ’(a b c d) 2) =⇒ c in programs, and so most implementations of Scheme use
(list-ref ’(a b c . d) 2) =⇒ c them internally for that purpose. Symbols are useful for
many other applications; for instance, they may be used
the way enumerated values are used in C and Pascal.
(map proc list1 list2 . . . ) procedure
A symbol literal is formed using quote.
The lists must all have the same length. proc must be a
procedure. If the lists are non-empty, proc must take as Hello =⇒ Hello
many arguments as there are lists and must return a single ’H\x65;llo =⇒ Hello
value. ’λ =⇒ λ
’\x3BB; =⇒ λ
The map procedure applies proc element-wise to the ele- (string->symbol "a b") =⇒ a\x20;b
ments of the lists and returns a list of the results, in order. (string->symbol "a\\b") =⇒ a\x5C;b
The dynamic order in which proc is applied to the elements ’a\x20;b =⇒ a\x20;b
of the lists is unspecified. ’|a b| ; syntax violation
46 Revised5.91 Scheme
; (illegal character printed for humans to read, and characters, which are abstract
; vertical bar) entities that map to glyphs (sometimes in a way that’s sensitive
’a\nb ; syntax violation to surrounding characters). Furthermore, different sequences
; (illegal use of backslash) of code points sometimes correspond to the same character.
’a\x20 ; syntax violation The relationships among code points, characters, and glyphs
; (missing semi-colon to are subtle and complex.
; terminate \x escape)
Despite this complexity, most things that a literate human
would call a “character” can be represented by a single code
(symbol? obj ) procedure point in Unicode (though there may exist code-point sequences
that represent that same character). For example, Roman let-
Returns #t if obj is a symbol, otherwise returns #f. ters, Cyrillic letters, Hebrew consonants, and most Chinese
(symbol? ’foo) =⇒ #t characters fall into this category. Thus, the “code point” ap-
(symbol? (car ’(a b))) =⇒ #t proximation of “character” works well for many purposes. More
(symbol? "bar") =⇒ #f specifically, Scheme characters correspond to Unicode scalar
(symbol? ’nil) =⇒ #t values, which includes all code points except those designated
(symbol? ’()) =⇒ #f as surrogates. A surrogate is a code point in the range #xD800
(symbol? #f) =⇒ #f to #xDFFF that is used in pairs in the UTF-16 encoding to
encode a supplementary character (whose code is in the range
(symbol->string symbol ) procedure #x10000 to #x10FFFF).
that is fixed when the string is created. The valid indexes (string=? string1 string2 string3 . . . ) procedure
of a string are the exact non-negative integers less than Returns #t if the strings are the same length and contain
the length of the string. The first character of a string has the same characters in the same positions, otherwise re-
index 0, the second has index 1, and so on. turns #f.
In phrases such as “the characters of string beginning with (string=? "Strae" "Strasse")=⇒ #f
index start and ending with index end ,” it is understood
that the index start is inclusive and the index end is ex-
clusive. Thus if start and end are the same index, a null (string<? string1 string2 string3 . . . ) procedure
substring is referred to, and if start is zero and end is the (string>? string1 string2 string3 . . . ) procedure
length of string, then the entire string is referred to. (string<=? string1 string2 string3 . . . ) procedure
(string>=? string1 string2 string3 . . . ) procedure
The length of a vector is the number of elements that it (let ((vec (vector 0 ’(2 2 2 2) "Anna")))
contains. This number is a non-negative integer that is (vector-set! vec 1 ’("Sue" "Sue"))
fixed when the vector is created. The valid indexes of a vec)
=⇒ #(0 ("Sue" "Sue") "Anna")
vector are the exact non-negative integers less than the
length of the vector. The first element in a vector is indexed (vector-set! ’#(0 1 2) 1 "doe")
by zero, and the last element is indexed by one less than =⇒ unspecified
the length of the vector. ; constant vector
Like list constants, vector constants must be quoted: ; may raise &contract exception
’#(0 (2 2 2 2) "Anna")
=⇒ #(0 (2 2 2 2) "Anna") (vector->list vector ) procedure
(list->vector list) procedure
(vector? obj ) procedure The vector->list procedure returns a newly allocated list
of the objects contained in the elements of vector . The
Returns #t if obj is a vector, otherwise returns #f. list->vector procedure returns a newly created vector
initialized to the elements of the list list.
(make-vector k ) procedure (vector->list ’#(dah dah didah))
(make-vector k fill ) procedure =⇒ (dah dah didah)
Returns a newly allocated vector of k elements. If a second (list->vector ’(dididit dah))
argument is given, then each element is initialized to fill . =⇒ #(dididit dah)
Otherwise the initial contents of each element is unspeci-
fied. (vector-fill! vector fill ) procedure
Stores fill in every element of vector and returns the un-
(vector obj . . . ) procedure specified value.
Returns a newly allocated vector whose elements contain
the given arguments. Analogous to list.
9.17. Errors and violations
(vector ’a ’b ’c) =⇒ #(a b c)
(define list-length
9.18. Control features (lambda (obj)
(call-with-current-continuation
This chapter describes various primitive procedures which (lambda (return)
control the flow of program execution in special ways. (letrec ((r
(lambda (obj)
(cond ((null? obj) 0)
(apply proc arg1 . . . args) procedure ((pair? obj)
Proc must be a procedure and args must be a list. Calls (+ (r (cdr obj)) 1))
proc with the elements of the list (append (list arg1 (else (return #f))))))
. . . ) args) as the actual arguments. (r obj))))))
Each iteration begins by evaluating htesti; if the result is not all of the desired structure is known in advance. If
false (see section 9.11), then the hcommandi expressions are no unquote or unquote-splicing forms appear within
evaluated in order for effect, the hstepi expressions are eval- the hqq templatei, the result of evaluating (quasiquote
uated in some unspecified order, the hvariableis are bound hqq templatei) is equivalent to the result of evaluating
to fresh locations, the results of the hstepis are stored in the (quote hqq templatei).
bindings of the hvariableis, and the next iteration begins.
If an (unquote hexpressioni . . . ) form appears inside a
If htesti evaluates to a true value, then the hexpressionis hqq templatei, however, the hexpressionis are evaluated
are evaluated from left to right and the value(s) of the (“unquoted”) and their results are inserted into the struc-
last hexpressioni is(are) returned. If no hexpressionis are ture instead of the unquote form.
present, then the value of the do expression is the unspec-
ified value. If an (unquote-splicing hexpressioni . . . ) form appears
inside a hqq templatei, then the hexpressionis must evalu-
The region of the binding of a hvariablei consists of the ate to lists; the opening and closing parentheses of the list
entire do expression except for the hinitis. It is a syntax are then “stripped away” and the elements of the lists are
violation for a hvariablei to appear more than once in the inserted in place of the unquote-splicing form.
list of do variables.
unquote-splicing and multi-operand unquote forms
A hstepi may be omitted, in which case the effect is the
must appear only within a list or vector hqq templatei.
same as if (hvariablei hiniti hvariablei) had been written
instead of (hvariablei hiniti). As noted in section 3.3.5, (quasiquote hqq templatei)
(do ((vec (make-vector 5)) may be abbreviated `hqq templatei, (unquote
(i 0 (+ i 1))) hexpressioni) may be abbreviated ,hexpressioni, and
((= i 5) vec) (unquote-splicing hexpressioni) may be abbreviated
(vector-set! vec i i)) =⇒ #(0 1 2 3 4) ,@hexpressioni.
It is a syntax violation if any of the identifiers quasiquote, list of keywords being bound. The hformis are arbitrary
unquote, or unquote-splicing appear in positions within forms.
a hqq templatei otherwise than as described above.
Semantics: The hformis are expanded in the syntactic envi-
The following grammar for quasiquote expressions is not ronment obtained by extending the syntactic environment
context-free. It is presented as a recipe for generating an of the let-syntax form with macros whose keywords are
infinite number of production rules. Imagine a copy of the the hkeywordis, bound to the specified transformers. Each
following rules for D = 1, 2, 3, . . .. D keeps track of the binding of a hkeywordi has the hformis as its region.
nesting depth.
The hformis of a let-syntax form are treated, whether
hquasiquotationi −→ hquasiquotation 1i in definition or expression context, as if wrapped in an
hqq template 0i −→ hexpressioni implicit begin, see section 9.5.7. Thus, internal definitions
hquasiquotation Di −→ (quasiquote hqq template Di) in the result of expanding the hformis have the same region
hqq template Di −→ hsimple datumi as any definition appearing in place of the let-syntax form
| hlist qq template Di would have.
| hvector qq template Di
| hunquotation Di (let-syntax ((when (syntax-rules ()
((when test stmt1 stmt2 ...)
hlist qq template Di −→ (hqq template or splice Di*)
(if test
| (hqq template or splice Di+ . hqq template Di) (begin stmt1
| hquasiquotation D + 1i stmt2 ...))))))
hvector qq template Di −→ #(hqq template or splice Di*) (let ((if #t))
hunquotation Di −→ (unquote hqq template D − 1i) (when if (set! if ’now))
hqq template or splice Di −→ hqq template Di if)) =⇒ now
| hsplicing unquotation Di
hsplicing unquotation Di −→ (let ((x ’outer))
(unquote-splicing hqq template D − 1i*) (let-syntax ((m (syntax-rules () ((m) x))))
| (unquote hqq template D − 1i*) (let ((x ’inner))
(m)))) =⇒ outer
In hquasiquotationis, a hlist qq template Di can some- (let ()
times be confused with either an hunquotation Di or (let-syntax
a hsplicing unquotation Di. The interpretation as an ((def (syntax-rules ()
hunquotationi or hsplicing unquotation Di takes prece- ((def stuff ...) (define stuff ...)))))
dence. (def foo 42))
foo) =⇒ 42
(let ()
9.20. Binding constructs for syntactic key- (let-syntax ())
words 5) =⇒ 5
Underscores also match arbitrary input subforms but are • P is a pattern datum (any nonlist, nonvector, non-
not pattern variables and so cannot be used to refer to those symbol datum) and F is equal to P in the sense of the
elements. Multiple underscores may appear in a hpatterni. equal? procedure.
A literal identifier matches an input subform if and only
if the input subform is an identifier and either both its When a macro use is transcribed according to the template
occurrence in the input expression and its occurrence in of the matching hsyntax rulei, pattern variables that occur
the list of literals have the same lexical binding, or the two in the template are replaced by the subforms they match
identifiers have the same name and both have no lexical in the input.
binding. Pattern data and identifiers that are not pattern variables
A subpattern followed by an ellipsis can match zero or more or ellipses are copied directly into the output. A subtem-
elements of the input. plate followed by an ellipsis expands into zero or more oc-
More formally, an input form F matches a pattern P if and currences of the subtemplate. Pattern variables that occur
only if one of the following holds: in subpatterns followed by one or more ellipses may oc-
cur only in subtemplates that are followed by (at least) as
• P is an underscore ( ). many ellipses. These pattern variables are replaced in the
output by the input subforms to which they are bound,
• P is a pattern variable. distributed as specified. If a pattern variable is followed
• P is a literal identifier and F is an identifier such that by more ellipses in the subtemplate than in the associ-
both P and F would refer to the same binding if both ated subpattern, the input form is replicated as necessary.
were to appear in the output of the macro outside of The subtemplate must contain at least one pattern vari-
any bindings inserted into the output of the macro. able from a subpattern followed by an ellipsis, and for at
(If neither of two like-named identifiers refers to any least one such pattern variable, the subtemplate must be
binding, i.e., both are undefined, they are considered followed by exactly as many ellipses as the subpattern in
to refer to the same binding.) which the pattern variable appears. (Otherwise, the ex-
pander would not be able to determine how many times
• P is of the form (P1 ... Pn ) and F is a list of n the subform should be repeated in the output.) It is a
elements that match P1 through Pn . syntax violation if the consraints of this paragraph are not
met.
• P is of the form (P1 ... Pn . Px ) and F is a list
or improper list of n or more elements whose first n A template of the form (hellipsisi htemplatei) is identi-
elements match P1 through Pn and whose nth cdr cal to htemplatei, except that ellipses within the template
matches Px . have no special meaning. That is, any ellipses contained
within htemplatei are treated as ordinary identifiers. In
• P is of the form (P1 ... Pk Pe hellipsisi Pm+1 ... particular, the template (... ...) produces a single el-
Pn ), where hellipsisi is the identifier ... and F is a lipsis, .... This allows syntactic abstractions to expand
proper list of n elements whose first k elements match into forms containing ellipses.
P1 through Pk , whose next m−k elements each match
Pe , and whose remaining n − m elements match Pm+1 As an example, if let and cond are defined as in sec-
through Pn . tion 9.5.6 and appendix B then they are hygienic (as re-
quired) and the following is not an error.
• P is of the form (P1 ... Pk Pe hellipsisi Pm+1 ...
Pn . Px ), where hellipsisi is the identifier ... and (let ((=> #f))
F is a list or improper list of n elements whose first (cond (#t => ’ok))) =⇒ ok
k elements match P1 through Pk , whose next m − k The macro transformer for cond recognizes => as a local
elements each match Pe , whose next n − m elements variable, and hence an expression, and not as the top-level
match Pm+1 through Pn , and whose nth and final cdr identifier =>, which the macro transformer treats as a syn-
matches Px . tactic keyword. Thus the example expands into
• P is of the form #(P1 ... Pn ) and F is a vector of n (let ((=> #f))
elements that match P1 through Pn . (if #t (begin => ’ok)))
• The last expression within the body of a lambda ex- htail sequencei
pression, shown as htail expressioni below, occurs in a htail sequencei −→ hexpressioni* htail expressioni
tail context.
where
(char-upcase #\i) =⇒ #\I These procedures return #t if their arguments are alpha-
(char-downcase #\i) =⇒ #\i betic, numeric, whitespace, upper case, lower case, or title
(char-titlecase #\i) =⇒ #\I case characters, respectively; otherwise they return #f.
(char-foldcase #\i) =⇒ #\i
A character is alphabetic if it is a Unicode letter, i.e. if
it is in one of the categories Lu, Ll, Lt, Lm, and Lo. A
(char-upcase #\ß) =⇒ #\ß
(char-downcase #\ß) =⇒ #\ß character is numeric if it is in categeory Nd. A character
(char-titlecase #\ß) =⇒ #\ß is whitespace if it is in one of the space, line, or para-
(char-foldcase #\ß) =⇒ #\ß graph separator categories (Zs, Zl or Zp), or if is Unicode
9 (Horizontal tabulation), Unicode 10 (Line feed), Unicode
(char-upcase #\Σ) =⇒ #\Σ 11 (Vertical tabulation), Unicode 12 (Form feed), or Uni-
(char-downcase #\Σ) =⇒ #\σ code 13 (Carriage return). A character is upper case if it
(char-titlecase #\Σ) =⇒ #\Σ has the Unicode “Uppercase” property, lower case if it has
(char-foldcase #\Σ) =⇒ #\σ the “Lowercase” property, and title case if it is in the Lt
general category.
(char-upcase #\ς) =⇒ #\Σ
(char-downcase #\ς) =⇒ #\ς (char-alphabetic? #\a) =⇒ #t
(char-titlecase #\ς) =⇒ #\Σ (char-numeric? #\1) =⇒ #t
10. Unicode 59
(char-whitespace? #\space) =⇒ #t
(char-whitespace? #\x00A0) =⇒ #t (string-downcase "Σ") =⇒ "σ"
(char-upper-case? #\Σ) =⇒ #t
(char-lower-case? #\σ) =⇒ #t ; Chi Alpha Omicron Sigma:
(char-lower-case? #\x00AA) =⇒ #t (string-upcase "XAOΣ") =⇒ "XAOΣ"
(char-title-case? #\I) =⇒ #f (string-downcase "XAOΣ") =⇒ "χαoς"
(char-title-case? #\x01C5) =⇒ #t (string-downcase "XAOΣΣ") =⇒ "χαoσς"
(string-downcase "XAOΣ Σ")=⇒ "χαoς σ"
(string-foldcase "XAOΣΣ") =⇒ "χαoσσ"
(string-upcase "χαoς") =⇒ "XAOΣ"
(char-general-category char ) procedure (string-upcase "χαoσ") =⇒ "XAOΣ"
Returns a symbol representing the Unicode general cate-
(string-titlecase "kNock KNoCK")
gory of char , one of Lu, Ll, Lt, Lm, Lo, Mn, Mc, Me, Nd, Nl,
=⇒ "Knock Knock"
No, Ps, Pe, Pi, Pf, Pd, Pc, Po, Sc, Sm, Sk, So, Zs, Zp, Zl, (string-titlecase "who’s there?")
Cc, Cf, Cs, Co, or Cn. =⇒ "Who’s There?"
(char-general-category #\a) =⇒ Ll (string-titlecase "r6rs") =⇒ "R6Rs"
(char-general-category #\space) (string-titlecase "R6RS") =⇒ "R6Rs"
=⇒ Zs
(char-general-category #\x10FFFF) Note: The case mappings needed for implementing
=⇒ Cn these procedures can be extracted from UnicodeData.txt,
SpecialCasing.txt, WordBreakProprty.txt (the “MidLet-
ter” property partly defines case-ignorable characters), and
CaseFolding.txt from the Unicode Consortium.
10.2. Strings
Since these procedures are locale-independent, they may not be
completely appropriate for some locales.
The length of a bytes object is the number of bytes it con- K must be a valid index of bytes.
tains. This number is fixed. A valid index into a bytes The bytes-u8-ref procedure returns the byte at index k
object is an exact, non-negative integer. The first byte of of bytes, as an octet.
a bytes object has index 0; the last byte has an index one The bytes-s8-ref procedure returns the byte at index k
less than the length of the bytes object. of bytes, as a (signed) byte.
Generally, the access procedures come in different flavors (let ((b1 (make-bytes 16 -127))
according to the size of the represented integer, and the (b2 (make-bytes 16 255)))
endianness of the representation. The procedures also dis- (list
tinguish signed and unsigned representations. The signed (bytes-s8-ref b1 0)
representations all use two’s complement. (bytes-u8-ref b1 0)
(bytes-s8-ref b2 0)
Like list and vector literals, literals representing bytes ob-
(bytes-u8-ref b2 0))) =⇒ (-127 129 -1 255)
jects must be quoted:
’#vu8(12 23 123) =⇒ #vu8(12 23 123)
(bytes-u32-native-ref bytes k ) procedure 255 255 255 255 255 255 255 253)))
(bytes-s32-native-ref bytes k ) procedure
(bytes-u32-set! bytes k n endianness) procedure (bytes-u64-ref b 8 (endianness little))
(bytes-s32-set! bytes k n endianness) procedure =⇒ 18302628885633695743
(bytes-u32-native-set! bytes k n) procedure (bytes-s64-ref b 8 (endianness little))
=⇒ -144115188075855873
(bytes-s32-native-set! bytes k n) procedure
(bytes-u64-ref b 8 (endianness big))
{k , . . . , k + 3} must be valid indices of bytes.. =⇒ 18446744073709551613
(bytes-s64-ref b 8 (endianness big))
These retrieve and set four-byte representations of num-
=⇒ -3
bers at indices {k , . . . , k + 3}, according to the endianness
specified by endianness. The procedures with u32 in their
names deal with the unsigned representation, those with
s32 with the two’s complement representation. (bytes=? bytes1 bytes2 ) procedure
The procedures with native in their names employ the Returns #t if bytes1 and bytes2 are equal—that is, if they
native endianness, and only work at aligned indices: k must have the same length and equal bytes at all valid indices.
be a multiple of 4.. It returns #f otherwise.
The . . . -set! procedures return the unspecified value.
(define b (bytes-ieee-single-native-ref bytes k ) procedure
(u8-list->bytes (bytes-ieee-single-ref bytes k endianness)
’(255 255 255 255 255 255 255 255 procedure
255 255 255 255 255 255 255 253)))
{k , . . . , k + 3} must be valid indices of bytes. For
(bytes-u32-ref b 12 (endianness little)) bytes-ieee-single-native-ref, k must be a multiple of
=⇒ 4261412863 4.
(bytes-s32-ref b 12 (endianness little))
These procedures return the inexact real that best repre-
=⇒ -33554433
sents the IEEE-754 single precision number represented by
(bytes-u32-ref b 12 (endianness big))
=⇒ 4294967293 the four bytes beginning at index k .
(bytes-s32-ref b 12 (endianness big))
=⇒ -3
(bytes-ieee-double-native-ref bytes k ) procedure
(bytes-ieee-double-ref bytes k endianness)
procedure
(bytes-u64-ref bytes k endianness) procedure {k , . . . , k + 7} must be valid indices of bytes. For
(bytes-s64-ref bytes k endianness) procedure bytes-ieee-double-native-ref, k must be a multiple of
(bytes-u64-native-ref bytes k ) procedure 8.
(bytes-s64-native-ref bytes k ) procedure
(bytes-u64-set! bytes k n endianness) procedure These procedures return the inexact real that best repre-
(bytes-s64-set! bytes k n endianness) procedure sents the IEEE-754 single precision number represented by
(bytes-u64-native-set! bytes k n) procedure the eight bytes beginning at index k .
(bytes-s64-native-set! bytes k n) procedure
{k , . . . , k + 7} must be valid indices of bytes. (bytes-ieee-single-native-set! bytes k x )
These retrieve and set eight-byte representations of num- procedure
bers at indices {k , . . . , k + 7}, according to the endianness (bytes-ieee-single-set! bytes k x endianness)
specified by endianness. The procedures with u64 in their procedure
names deal with the unsigned representation, those with {k , . . . , k + 3} must be valid indices of bytes. For
s64 with the two’s complement representation. bytes-ieee-single-native-set!, k must be a multiple
The procedures with native in their names employ the of 4. X must be a real number.
native endianness, and only work at aligned indices: k must These procedures store an IEEE-754 single precision rep-
be a multiple of 8. resentation of x into elements k through k + 3 of bytes, and
The . . . -set! procedures return the unspecified value. returns the unspecified value.
(define b
(u8-list->bytes (bytes-ieee-double-native-set! bytes k x )
’(255 255 255 255 255 255 255 255 procedure
12. List utilities 63
(forall =⇒ #f
even? ’(3 1 4 1 5 9))
(forall =⇒
even? ’(3 1 4 1 5 9 . 2))#f (fold-left (lambda (x count)
(forall even? ’(2 1 4 14)) =⇒ #t (if (odd? x) (+ count 1) count))
(forall even? ’(2 1 4 14 . 9)) 0
=⇒ &contract exception ’(3 1 4 1 5 9 2 6 5))
(forall (lambda (n) (and (even? n) n)) ’(2 1 4 14) =⇒ 6
=⇒ 14
(fold-left (lambda (max-len s)
=⇒ #t
(exists even? ’(3 1 4 1 5 9)) (max max-len (string-length s)))
(exists even? ’(3 1 1 5 9)) =⇒ #f 0
(exists even? ’(3 1 1 5 9 . 2)) ’("longest" "long" "longer"))
=⇒ &contract exception =⇒ 7
(exists (lambda (n) (and (even? n) n)) ’(2 1 4 14)
=⇒ 2 (fold-left cons ’(q) ’(a b c))
=⇒ ((((q) . a) . b) . c)
If more than one list is given, then they must all be the (fold-right cons ’() ’(1 2 3 4 5))
same length. kons must be a procedure; if the lists are non- =⇒ (1 2 3 4 5)
empty, it must take one more argument than there are lists.
The fold-left procedure iterates the kons procedure over (fold-right (lambda (x l)
an accumulator value and the values of the lists from left (if (odd? x) (cons x l) l))
to right, starting with an accumulator value of nil . More ’()
specifically, fold-left returns nil if the lists are empty. ’(3 1 4 1 5 9 2 6 5))
If they are not empty, kons is first applied to nil and the =⇒ (3 1 1 5 9 5)
respective first elements of the lists in order. The result
(fold-right cons ’(q) ’(a b c))
becomes the new accumulator value, and kons is applied
=⇒ (a b c q)
to new accumulator value and the respective next elements
of the list. This step is repeated until the end of the list is (fold-right + 0 ’(1 2 3) ’(4 5 6))
reached; then the accumulator value is returned. =⇒ 21
(fold-left + 0 ’(1 2 3 4 5))=⇒ 15
(remv obj list) procedure Rationale: Although they are ordinarily used as predicates,
(remq obj list) procedure memp, member, memv, memq, do not have question marks in their
names because they return useful values rather than just #t or
Proc must be a procedure; it must take a single argument
#f.
if list is non-empty. Each of these procedures returns a list
of the elements of list that do not satisfy a given condi-
tion. The remp procedure successively applies proc to the (assp proc al ) procedure
elements of list and returns a list of the values of list for (assoc obj al ) procedure
which proc returned #f. The remove, remv, and remq pro- (assv obj al ) procedure
cedures return a list of the elements that are not obj . The (assq obj al ) procedure
remq procedure uses eq? to compare obj with the elements
Al (for “association list”) must be the empty list or a chain
of list, while remv uses eqv? and remove uses equal?.
of pairs where each car contains a pair of size according to
(remp even? ’(3 1 4 1 5 9 2 6 5)) the conditions specified below. Proc must be a procedure;
=⇒ (3 1 1 5 9 2 5) it must take a single argument if al is non-empty.
These procedures find the first pair in al whose car field
(remove 1 ’(3 1 4 1 5 9 2 6 5))
=⇒ (3 4 5 9 2 6 5) satisfies a given condition, and returns that pair without
traversing al further. If no pair in al satisfies the condition,
(remv 1 ’(3 1 4 1 5 9 2 6 5)) then #f is returned; in that case, al must be a list. The
=⇒ (3 4 5 9 2 6 5) assp procedure successively applies proc to the car fields
of al and looks for a pair for which it returns a true value.
(remq ’foo ’(bar foo baz)) =⇒ (bar baz) The assoc, assv, and assq procedures look for a pair that
has obj as its car. The assoc procedure uses equal? to
compare obj with the car fields of the pairs in al , while
assv uses eqv? and assq uses eq?.
(memp proc l ) procedure
(member obj l ) procedure (define d ’((3 a) (1 b) (4 c)))
(memv obj l ) procedure
(memq obj l ) procedure (assp even? d) =⇒ (4 c)
(assp odd? d) =⇒ (3 a)
Proc must be a procedure; it must take a single argument (define e ’((a 1) (b 2) (c 3)))
if l is non-empty. l must be the empty list or a chain of (assq ’a e) =⇒ (a 1)
pairs of size according to the conditions stated below. (assq ’b e) =⇒ (b 2)
(assq ’d e) =⇒ #f
These procedures return the first sublist of l whose car (assq (list ’a) ’(((a)) ((b)) ((c))))
satisfies a given condition, where the subchains of l are =⇒ #f
the chains of pairs returned by (list-tail l k ) for k less (assoc (list ’a) ’(((a)) ((b)) ((c))))
than the length of l . The memp procedure applies proc to =⇒ ((a))
the cars of the sublists of l until it finds one for which (assq 5 ’((2 3) (5 7) (11 13)))
proc returns a true value without traversing l further. The =⇒ unspecified
member, memv, and memq procedures look for the first oc- (assv 5 ’((2 3) (5 7) (11 13)))
currence of obj . If l does not contain an element satisfying =⇒ (5 7)
the condition, then #f (not the empty list) is returned; in
that case, l must be a list. The member procedure uses
13. Records
equal? to compare obj with the elements of l , while memv
uses eqv? and memq uses eq?. This section describes abstractions for creating new data
types representing records—data structures with named
(memp even? ’(3 1 4 1 5 9 2 6 5)) fields. The record mechanism comes in four libraries:
=⇒ (4 1 5 9 2 6 5)
• the (r6rs records implicit) library, an implicit- This section uses the rtd and constructor-descriptor pa-
naming syntactic layer that extends the explicit- rameter names for arguments that must be record-type
naming syntactic layer, allowing the names of the de- descriptors and constructor descriptors, respectively (see
fined procedures to be determined implicitly from the section 13.1).
names of the record type and fields, and
• the (r6rs records inspection) library, a set of in- 13.1. Procedural layer
spection procedures.
The procedural layer is provided by the (r6rs records
The procedural layer allows programs to construct new procedural) library.
record types and the associated procedures for creating and
manipulating records dynamically. It is particularly use-
(make-record-type-descriptor name procedure
ful for writing interpreters that construct host-compatible
parent uid sealed? opaque? fields)
record types. It may also serve as a target for expansion
of the syntactic layers. Returns a record-type descriptor, or rtd, representing a
record type distinct from all built-in types and other record
The explicit-naming syntactic layer provides a basic syn- types.
tactic interface whereby a single record definition serves
as a shorthand for the definition of several record creation The name argument must be a symbol naming the record
and manipulation routines: a construction procedure, a type; it is intended purely for informational purposes and
predicate, field accessors, and field mutators. As the name may be used for printing by the underlying Scheme system.
suggests, the explicit-naming syntactic layer requires the The parent argument must be either #f or an rtd. If it is
programmer to name each of these procedures explicitly. an rtd, the returned record type, t, extends the record type
The implicit-naming syntactic layer extends the explicit- p represented by parent. Each record of type t is also a
naming syntactic layer by allowing the names for the con- record of type p, and all operations applicable to a record
struction procedure, predicate, accessors, and mutators to of type p are also applicable to a record of type t, except
be determined automatically from the name of the record for inspection operations if t is opaque but p is not. An
and names of the fields. This establishes a standard naming exception with condition type &contract is raised if parent
convention and allows record-type definitions to be more is sealed (see below).
succinct, with the downside that the procedure definitions The extension relationship is transitive in the sense that a
cannot easily be located via a simple search for the proce- type extends its parent’s parent, if any, and so on.
dure name. The programmer may override some or all of
The uid argument must be either #f or a symbol. If uid
the default names by specifying them explicitly, as in the
is a symbol, the record-creation operation is nongenerative
explicit-naming syntactic layer.
i.e., a new record type is created only if no previous call to
The two syntactic layers are designed to be fully compati- make-record-type-descriptor was made with the uid .
ble; the implicit-naming layer is simply a conservative ex- If uid is #f, the record-creation operation is generative,
tension of the explicit-naming layer. The design makes i.e., a new record type is created even if a previous call to
both explicit-naming and implicit-naming definitions rea- make-record-type-descriptor was made with the same
sonably natural while allowing a seamless transition be- arguments.
tween explicit and implicit naming.
If make-record-type-descriptor is called twice with the
Each of these layers permits record types to be extended same uid symbol, the parent arguments in the two calls
via single inheritance, allowing record types to model hier- must be eqv?, the fields arguments equal?, the sealed? ar-
archies that occur in applications like algebraic data types guments boolean-equivalent (both false or both non-false),
as well as single-inheritance class systems. and the opaque? arguments boolean-equivalent. If these
Each of the layers also supports generative and nongener- conditions are not met, an exception with condition type
ative record types. &contract is raised when the second call occurs. If they
are met, the second call returns, without creating a new
The inspection procedures allow programs to obtain from a record type, the same record-type descriptor (in the sense
record instance a descriptor for the type and from there ob- of eqv?) as the first call.
tain access to the fields of the record instance. This allows
Note: Users are encouraged to use symbol names constructed
the creation of portable printers and inspectors. A program
using the UUID namespace (for example, using the record-type
may prevent access to a record’s type and thereby protect
name as a prefix) for the uid argument.
the information stored in the record from the inspection
mechanism by declaring the type opaque. Thus, opacity as The sealed? flag must be a boolean. If true, the returned
presented here can be used to enforce abstraction barriers. record type is sealed, i.e., it cannot be extended.
13. Records 67
The opaque? flag must be a boolean. If true, the record Rationale: Multiple inheritance was considered but omitted
type is opaque. If passed an instance of the record type, from the records facility, as it raises a number of semantic issues
record? returns #f and record-rtd (see “Inspection” be- such as sharing among common parent types.
low) raises an exception with condition type &contract.
The record type is also opaque if an opaque parent is sup- (record-type-descriptor? obj ) procedure
plied. If opaque? is false and an opaque parent is not sup-
Returns #t if the argument is a record-type descriptor, #f
plied, the record is not opaque.
otherwise.
The fields argument must be a list of field specifiers. Each
field specifier must be a list of the form (mutable name) or (make-record-constructor-descriptor rtd procedure
a list of the form (immutable name). Each name must be parent-constructor-descriptor protocol )
a symbol and names the corresponding field of the record
type; the names need not be distinct. A field identified as Returns a record-constructor descriptor (or constructor de-
mutable may be modified, whereas an attempt to obtain a scriptor for short) that can be used to create record con-
mutator for a field identified as immutable raises an excep- structors (via record-constructor; see below) or other
tion with condition type &contract. Where field order is constructor descriptors. rtd must be a record-type descrip-
relevant, e.g., for record construction and field access, the tor. protocol must be a procedure or #f. If it is #f, a default
fields are considered to be ordered as specified, although no protocol procedure is supplied. If protocol is a procedure, it
particular order is required for the actual representation of is called by record-constructor with a single argument
a record instance. p and must return a procedure that creates and returns an
instance of the record type using p as described below.
The specified fields are added to the parent fields, if any, to
determine the complete set of fields of the returned record If rtd is not an extension of another record type, then
type. parent-constructor-descriptor must be #f. In this case,
protocol ’s argument p is a procedure new that expects one
A record type is considered immutable if each of its com- parameter for every field of rtd and returns a record in-
plete set of fields is immutable, and is mutable otherwise. stance with the fields of rtd initialized to its arguments.
A generative record-type descriptor created by a call to The procedure returned by protocol may take any number
make-record-type-descriptor is not eqv? to any record- of arguments but must call new with the number of argu-
type descriptor (generative or nongenerative) created by ments it expects and return the resulting record instance,
another call to make-record-type-descriptor. A gen- as shown in the simple example below.
erative record-type descriptor is eqv? only to itself, i.e., (lambda (new )
(eqv? rtd1 rtd2 ) iff (eq? rtd1 rtd2 ). Also, two non- (lambda (v1 ...)
generative record-type descriptors are eqv? iff they were (new v1 ...)))
created by calls to make-record-type-descriptor with
the same uid arguments. Here, the call to new returns a record whose fields are sim-
Rationale: The record and field names passed to ply initialized with the arguments v1 .... The expression
make-record-type-descriptor and appearing in the explicit- above is equivalent to (lambda (new ) new ).
naming syntactic layer are for informational purposes only, e.g.,
for printers and debuggers. In particular, the accessor and mu- If rtd is an extension of another record type
tator creation routines do not use names, but rather field in- parent-rtd , parent-constructor-descriptor must be
dices, to identify fields. a constructor descriptor of parent-rtd or #f. If
parent-constructor-descriptor is #f, a default constructor
Thus, field names are not required to be distinct in the proce-
dural or implicit-naming syntactic layers. This relieves macros
descriptor is supplied. In this case, p is a procedure that
and other code generators from the need to generate distinct accepts the same number of arguments as the constructor
names. of parent-constructor-descriptor and returns a procedure
new , which, as above, expects one parameter for every field
The record and field names are used in the implicit-naming syn- of rtd (not including parent fields) and returns a record
tactic layer for the generation of accessor and mutator names, instance with the fields of rtd initialized to its arguments
and duplicate field names may lead to accessor and mutator and the fields of parent-rtd and its parents initialized by
naming conflicts. the constructor of parent-constructor-descriptor . A simple
Rationale: Sealing a record type can help to enforce abstrac- protocol in this case might be written as follows.
tion barriers by preventing extensions that may expose imple- (lambda (p)
mentation details of the parent type. Type extensions also make (lambda (x1 ... v1 ...)
monomorphic code polymorphic and difficult to change the par- (let ((new (p x ...)))
ent class at a later time, and also prevent effective predictions (new v1 ...))))
of types by a compiler or human reader.
68 Revised5.91 Scheme
This passes some number of arguments x1 ... to p for returns the resulting construction procedure constructor
the constructor of parent-constructor-descriptor and calls for instances of the record type associated with
new with v1 ... to initialize the child fields. constructor-descriptor .
The constructor descriptors for a record type form a chain Two values created by constructor are equal according to
of protocols exactly parallel to the chain of record-type equal? iff they are eqv?, provided their record type is not
parents. Each constructor descriptor in the chain deter- used to implement any of the types explicitly mentioned in
mines the field values for the associated record type. Child the definition of equal?.
record constructors need not know the number or contents For any constructor returned by record-constructor, the
of parent fields, only the number of arguments required by following holds:
the parent constructor.
(let ((r (constructor v ...)))
protocol may be #f, specifying a default, only if rtd is not (eqv? r r)) =⇒ #t
an extension of another record type, or, if it is, if the parent
constructor-descriptor encapsulates a default protocol. In
For mutable records, but not necessarily for immutable
the first case, the default protocol procedure is equivalent
ones, the following hold. (A record of an mutable record
to the following:
type is mutable; a record of an immutable record type is
(lambda (p) immutable.)
(lambda field-values
(apply p field-values))) (let ((r (constructor v ...)))
(eq? r r)) =⇒ #t
or, simply, (lambda (p) p). (let ((f (lambda () (constructor v ...))))
(eq? (f) (f))) =⇒ #f
In the second case, the default protocol procedure returns
a constructor that accepts one argument for each of the
record type’s complete set of fields (including those of the
parent record type, the parent’s parent record type, etc.) (record-predicate rtd ) procedure
and returns a record with the fields initialized to those ar- Returns a procedure that, given an object obj , returns a
guments, with the field values for the parent coming before boolean that is #t iff obj is a record of the type represented
those of the extension in the argument list. by rtd .
Even if rtd extends another record type,
parent-constructor-descriptor may also be #f, in which (record-accessor rtd k ) procedure
case a constructor with default protocol is supplied. K must be a valid field index of rtd . The record-accessor
Rationale: The constructor-descriptor mechanism is an infra- procedure returns a one-argument procedure that, given a
structure for creating specialized constructors, rather than just record of the type represented by rtd , returns the value of
creating default constructors that accept the initial values of the selected field of that record.
all the fields as arguments. This infrastructure achieves full
generality while leaving each level of an inheritance hierarchy in The field selected is the one corresponding the the k th
control over its own fields and allowing child record definitions element (0-based) of the fields argument to the invocation
to be abstracted away from the actual number and contents of of make-record-type-descriptor that created rtd . Note
parent fields. that k cannot be used to specify a field of any type rtd
The design allows the initial values of the fields to be specially extends.
computed or to default to constant values. It also allows for op- If the accessor procedure is given something other than a
erations to be performed on or with the resulting record, such record of the type represented by rtd , an exception with
as the registration of a widget record for finalization. More- condition type &contract is raised. Records of the type
over, the constructor-descriptor mechanism allows the creation represented by rtd include records of extensions of the type
of such initializers in a modular manner, separating the initial- represented by rtd .
ization concerns of the parent types from those of the exten-
sions.
(record-mutator rtd k ) procedure
The mechanism described here achieves complete generality
without cluttering the syntactic layer, sacrificing a bit of no- K must be a valid field index of rtd . The record-mutator
tational convenience in special cases. procedure returns a two-argument procedure that, given
a record r of the type represented by rtd and an object
obj , stores obj within the field of r specified by k . The k
(record-constructor constructor-descriptor ) procedure argument is as in record-accessor. If k specifies an im-
Calls the protocol of constructor-descriptor (as de- mutable field, an exception with condition type &contract
scribed for make-record-constructor-descriptor) and is raised. The mutator returns the unspecified value.
13. Records 69
The explicit-naming syntactic layer is provided by the hField namei, haccessor namei, and hmutator namei
(r6rs records explicit) library. must all be identifiers. The first form de-
clares an immutable field called hfield namei, with
The record-type-defining form define-record-type is a
the corresponding accessor named hacccessor namei.
definition and can appear anywhere any other hdefinitioni
The second form declares a mutable field called
can appear.
hfield namei, with the corresponding accessor named
hacccessor namei, and with the corresponding muta-
(define-record-type hname speci hrecord clausei*) tor named hmutator namei.
syntax The hfield nameis become, as symbols, the names of
A define-record-type form defines a record type along the fields of the record type being created, in the same
with associated constructor descriptor and constructor, order. They are not used in any other way.
70 Revised5.91 Scheme
(set-point3-y! p3-1 17) case, the name of the construction procedure is generated
(point3-y p3-1) =⇒ 17) by prefixing the record name with make-, and the predi-
cate name is generated by adding a question mark (?) to
(record-rtd p3-1) the end of the record name. For example, if the record
=⇒ (record-type-descriptor point3) name is frob, the name of the construction procedure is
make-frob, and the predicate name is frob?.
(define-record-type (ex1 make-ex1 ex1?)
(protocol (lambda (new) (lambda a (new a)))) Second, the syntax of hfield-speci is extended to allow
(fields (immutable f ex1-f))) the accessor and mutator names to be omitted. That is,
hfield-speci can take one of the following forms as well as
(define ex1-i1 (make-ex1 1 2 3)) the forms described in the preceding section.
(ex1-f ex1-i1) =⇒ ’(1 2 3)
(immutable hfield namei)
(define-record-type (ex2 make-ex2 ex2?) (mutable hfield namei)
(protocol
(lambda (new) (lambda (a . b) (new a b)))) If hfield-speci takes one of these forms, the accessor name
(fields (immutable a ex2-a) is generated by appending the record name and field name
(immutable b ex2-b))) with a hyphen separator, and the mutator name (for a
mutable field) is generated by adding a -set! suffix to the
(define ex2-i1 (make-ex2 1 2 3)) accessor name. For example, if the record name is frob and
(ex2-a ex2-i1) =⇒ 1 the field name is widget, the accessor name is frob-widget
(ex2-b ex2-i1) =⇒ ’(2 3) and the mutator name is frob-widget-set!.
(define-record-type (unit-vector Any definition that takes advantage of implicit naming can
make-unit-vector be rewritten trivially to a definition that conforms to the
unit-vector?) syntax of the explicit-naming layer merely by specifing the
(protocol names explicitly. For example, the implicit-naming layer
(lambda (new) record definition:
(lambda (x y z)
(let ((length (+ (* x x) (* y y) (* z z)))) (define-record-type frob
(new (/ x length) (fields (mutable widget))
(/ y length) (protocol
(/ z length)))))) (lambda (c) (c (make-widget n)))))
(fields (immutable x unit-vector-x)
(immutable y unit-vector-y) is equivalent to the following explicit-naming layer record
(immutable z unit-vector-z)))
definition.
(define-record-type (frob make-frob frob?)
(fields (mutable widget
13.3. Implicit-naming syntactic layer frob-widget frob-widget-set!))
(protocol
(lambda (c) (c (make-widget n)))))
The implicit-naming syntactic layer is provided by the
(r6rs records implicit) library.
The define-record-type form of the implicit-naming With the implicit-naming layer, one can choose to specify
syntactic layer is a conservative extension of the just some of the names explicitly; for example, the follow-
define-record-type form of the explicit-naming layer: a ing overrides the choice of accessor and mutator names for
define-record-type form that conforms to the syntax of the widget field.
the explicit-naming layer also conforms to the syntax of the (define-record-type frob
implicit-naming layer, and any definition in the implicit- (fields (mutable widget getwid setwid!))
naming layer can be understood by its translation into the (protocol
explicit-naming layer. (lambda (c) (c (make-widget n)))))
(record-type-descriptor hrecord namei) syntax Returns the parent of the record-type descriptor rtd , or #f
if it has none.
This is the same as record-type-descriptor from the
(r6rs records explicit) library.
(record-type-uid rtd ) procedure
Returns the uid of the record-type descriptor rtd, or #f if
(record-constructor-descriptor hrecord namei) it has none. (An implementation may assign a generated
syntax uid to a record type even if the type is generative, so the
return of a uid does not necessarily imply that the type is
This is the same as record-constructor-descriptor
nongenerative.)
from the (r6rs records explicit) library.
14. Exceptions and conditions rent exception handler for the dynamic extent (as deter-
Scheme allows programs to deal with exceptional situa- mined by dynamic-wind) of the invocation of thunk .
tions using two cooperating facilities: The exception sys-
tem allows the program, when it detects an exceptional (guard (hvariablei hclause1 i hclause2 i . . . ) hbodyi)
situation, to pass control to an exception handler, and for syntax
dynamically establishing such exception handlers. Excep-
Syntax: Each hclausei should have the same form as a cond
tion handlers are always invoked with an object describing
clause. (Section 9.5.5.)
the exceptional situation. Scheme’s condition system pro-
vides a standardized taxonomy of such descriptive objects, Semantics: Evaluating a guard form evaluates hbodyi
as well as facility for defining new condition types. with an exception handler that binds the raised object to
hvariablei and within the scope of that binding evaluates
the clauses as if they were the clauses of a cond expres-
14.1. Exceptions sion. That implicit cond expression is evaluated with the
continuation and dynamic environment of the guard ex-
This section describes Scheme’s exception-handling and pression. If every hclausei’s htesti evaluates to false and
exception-raising constructs provided by the (r6rs there is no else clause, then raise is re-invoked on the
exceptions) library. raised object within the dynamic environment of the orig-
inal call to raise except that the current exception handler
Note: This specification follows SRFI 34 [29].
is that of the guard expression.
Exception handlers are one-argument procedures that de-
termine the action the program takes when an exceptional
(raise obj ) procedure
situation is signalled. The system implicitly maintains a
current exception handler. Raises a non-continuable exception by invoking the current
exception handler on obj . The handler is called with a con-
The program raises an exception by invoking the current
tinuation whose dynamic environment is that of the call to
exception handler, passing to it an object encapsulating
raise, except that the current exception handler is the one
information about the exception. Any procedure accepting
that was in place for the call to with-exception-handler
one argument may serve as an exception handler and any
that installed the handler being called. The continuation
object may be used to represent an exception.
of the handler raises a non-continuable exception with con-
The system maintains the current exception handler as dition type &non-continuable.
part of the dynamic environment of the program, the con-
text for dynamic-wind. The dynamic environment can be
(raise-continuable obj ) procedure
thought of as that part of a continuation that does not
specify the destination of any returned values. It includes Raises a continuable exception by invoking the current
the dynamic-wind context, and the current exception han- exception handler on obj . The handler is called with
dler. a continuation that is equivalent to the continuation of
the call to raise-continuable with these two exceptions:
When a safe script begins its execution, the current excep-
(1) the current exception handler is the one that was in
tion handler is expected to handle all &serious conditions
place for the call to with-exception-handler that in-
by interrupting execution, reporting that an exception has
stalled the handler being called, and (2) if the handler
been raised, and displaying information about the condi-
being called returns, then it will again become the cur-
tion object that was provided. The handler may then exit,
rent exception handler. If the handler returns, the value(s)
or may provide a choice of other options. Moreover, the
it returns become(s) the value(s) returned by the call to
exception handler is expected to return when passed any
raise-continuable.
other (“non-serious”) condition. Interpretation of these ex-
pectations necessarily depends upon the nature of the sys- (call-with-current-continuation
tem in which scripts are executed, but the intent is that (lambda (k)
users perceive the raising of an exception as a controlled (with-exception-handler
(lambda (x)
escape from the situation that raised the exception, not as
(display "condition: ")
a crash.
(write x)
(newline)
(with-exception-handler handler thunk ) procedure (k ’exception))
(lambda ()
Handler must be a procedure that accepts one argument. (+ 1 (raise ’an-error))))))
The with-exception-handler procedure returns the re- prints: condition: an-error
sult(s) of invoking thunk . Handler is installed as the cur- =⇒ exception
74 Revised5.91 Scheme
(guard (condition
(with-exception-handler
(else
(lambda (x)
(display "something went wrong")
42)
(newline)
(lambda ()
’dont-care))
(+ (raise-continuable #f)
(+ 1 (raise ’an-error)))
23))) =⇒ 65
prints: something went wrong
=⇒ dont-care
(call-with-current-continuation
(lambda (k)
(with-exception-handler 14.2. Conditions
(lambda (x)
(display "reraised ") (write x) (newline) The section describes’s Scheme (r6rs conditions) li-
(k ’zero))
brary for creating and inspecting condition types and val-
(lambda ()
(guard (condition
ues. A condition value encapsulates information about an
((positive? condition) ’positive) exceptional situation, or exception. Scheme also defines a
((negative? condition) ’negative)) number of basic condition types.
(raise 1))))))
Note: This specification follows SRFI 35 [30].
=⇒ positive
This type describes conditions that can safely be ignored. (define-condition-type &defect &violation
defect?)
&serious condition type This type describes defects in the program.
(serious-condition? obj ) procedure
This condition type could be defined by
&lexical condition type
(define-condition-type &serious &condition
(lexical-violation? obj ) procedure
serious-condition?)
This condition type could be defined by
This type describes conditions serious enough that they
cannot safely be ignored. This condition type is primarily (define-condition-type &lexical &defect
intended as a supertype of other condition types. lexical-violation?)
This type describes syntax violations at the level of the
&error condition type read syntax.
(error? obj ) procedure
This condition type could be defined by
&syntax condition type
(define-condition-type &error &serious
(syntax-violation? obj ) procedure
error?)
This condition type could be defined by
This type describes errors, typically caused by something
that has gone wrong in the interaction of the program with (define-condition-type &syntax &violation
the external world or the user. syntax-violation?
(form syntax-violation-form)
(subform syntax-violation-subform))
&violation condition type
(violation? obj ) procedure This type describes syntax violations at the level of the li-
This condition type could be defined by brary syntax. The form field contains the erroneous syntax
object or a datum representing that code of the erroneous
(define-condition-type &violation &serious
violation?) form. The subform field may contain an optional syntax
object or datum within the erroneous form that more pre-
This type describes violations of the language standard or a cisely locates the violation. It can be #f to indicate the
library standard, typically caused by a programming error. absence of more precise information.
A condition of this type specifies that an operation tried to hIdentifiersis other than those listed above may be used
operate on an non-existent named file under the assump- as hfile-options nameis; they have implementation-specific
tion that it exists. meaning, if any.
80 Revised5.91 Scheme
Bytes may or may not be a bytes object returned by (reader-chunk-size reader ) procedure
make-i/o-buffer. Returns a positive exact integer that represents a recom-
Count may or may not be the same as the chunk size mended efficient size of the read operations on this reader.
of the reader. The result is typically the block size of the buffers of the
operating system. As such, it is only a hint for clients of the
• (available) reader—calls to the reader-read! procedure (see below)
Returns an estimate of the total number of bytes left in may specify a different read count.
the reader. The result is either an exact integer, or #f For a reader created by make-simple-reader, the result is
if no such estimate is possible. There is no guarantee the value that was supplied as the chunk-size argument to
that this estimate has any specific relationship to the make-simple-reader.
true number of available bytes.
byte stream as an exact integer counting the number of (open-bytes-reader bytes) procedure
bytes since the beginning of the stream. Otherweise, an
Returns a bytes reader that uses bytes, a bytes ob-
exception with condition type &contract is raised.
ject, as its contents. The result reader supports
For a reader created by make-simple-reader, the reader-get-position, reader-set-position!, and
reader-get-position tail-calls the get-position pro- reader-end-position operations. The effect of modify-
cedure of reader . ing the contents of bytes, after open-bytes-reader has
been called, on the reader is unspecified.
that these procedures check that their arguments are of the (writer-descriptor writer ) procedure
appropriate types. The operations that call them perform
For a writer created by make-simple-writer,
no checking beyond ensuring that their writer arguments
write-descriptor returns the value of the descriptor
are indeed writers, and, if applicable, that the writer sup-
field of the argument writer.
ports the operation. These procedures must raise excep-
tions with condition types as specified above when they For all other writers, the result is an unspecified value.
encounter an exceptional situation. When they do not, the
effects are unspecified.
(writer-chunk-size writer ) procedure
Get-position, set-position! , and end-position may be omit-
Returns a positive exact integer, and is the recommended
ted, in which case the corresponding arguments must be
efficient size of the write operations on this writer. As
#f.
such, it is only a hint for clients of the writer—calls to
writer-write! (see below) may specify a different write
• (write! bytes start count) count.
Start and count must be non-negative exact integers. For a writer created by make-simple-writer, the result is
The write! procedure writes up to count bytes in bytes the value of the chunk-size field of the argument writer.
object bytes starting at index start. Before writing
any bytes, write! blocks until it can write at least
one byte. The result is the number of bytes actually (writer-write! writer bytes start count) procedure
written as a positive exact integer. Start and count must be non-negative exact integers.
Bytes may or may not be a bytes object returned by Bytes must have at least start + count elements. The
make-i/o-buffer. writer-write! procedure writes up to count bytes in bytes
Count may or may not be the same as the chunk size object bytes starting at index start. Before writing any
of the reader. bytes, write-write! blocks until it can write at least one
byte. The result is the number of bytes actually written as
• (get-position) a positive exact integer.
When present, get-position returns the current posi- Bytes may or may not be a bytes object returned by
tion in the byte stream as an exact integer counting make-i/o-buffer, but writer-write! may operate more
the number of bytes since the beginning of the stream. efficiently if it is.
• (set-position! pos) Count may or may not be the same as the chunk size of the
When present, set-position! moves to position pos reader, but writer-write! may operate more efficiently if
(which must be a non-negative exact integer) in the it is.
stream. For a writer created by make-simple-writer, writer-write!
tail-calls the write! procedure of writer with the remain-
• (end-position)
ing arguments. For all other writers, the result values are
When present, end-position returns the byte position unspecified.
of the next end of file without changing the current
position.
(writer-has-get-position? writer ) procedure
• (close) (writer-get-position writer ) procedure
Marks the writer as closed, performs any necessary The writer-has-get-position? procedure #t if
cleanup, and releases the resources associated with the writer supports the writer-get-position pro-
writer. Further operations on the writer must raise an cedure, and #f otherwise. For a simple writer,
exception with condition type &contract. writer-has-get-position? returns #t if it has a
get-position procedure.
When writer-has-get-position? returns #t for writer ,
(writer-id writer ) procedure writer-get-position returns the current position in the
Returns string naming the writer, provided for infor- byte stream as an exact integer counting the number of
mational purposes only. For a file writer returned by bytes since the beginning of the stream. Otherwise, an
open-file-writer or open-file-reader+writer, the re- exception with condition type &contract is raised.
sult is a string representation of the file name. For a writer created by make-simple-writer,
For a writer created by make-simple-writer, the result is writer-get-position calls the get-position procedure of
the value of the id field of the argument writer. writer .
84 Revised5.91 Scheme
port typically provides simultaneous read and write access 15.3.3. Text transcoders
to a file or other data.
Several different Unicode encoding schemes describe stan-
This section uses the input-port, output-port, port param- dard ways to encode characters and strings as byte se-
eter names for arguments that must be input ports (or quences and to decode those sequences [51]. Within this
combined input/output ports), output ports (or combined document, a codec is a Scheme object that represents a
input/output ports), or any kind of port. Unicode or similar encoding scheme.
The text transcoders of this document generalize codecs
15.3.1. Condition type to deal with common end-of-line conventions and different
error-handling modes.
This library introduces the following condition type: A transcoder is an opaque object that represents some
specific bidirectional (but not necessarily lossless) trans-
lation between byte sequences and Unicode characters and
&i/o-port condition type strings. The transcoder specifies how procedures that per-
(i/o-port-error? obj ) procedure form textual input are to interpret input bytes as charac-
(i/o-error-port condition) procedure ters or strings. The transcoder also specifies how proce-
This condition type could be defined by dures that perform textual output are to translate charac-
ters into bytes. Moreover, the transcoder specifies a mode
(define-condition-type &i/o-port &i/o for handling encoding or decoding errors.
i/o-port-error?
(port i/o-error-port)) A transcoder parameter name means that the correspond-
ing argument must be a transcoder.
(define-condition-type &i/o-decoding &i/o-port If a codec for an input port encounters an invalid or in-
i/o-decoding-error? complete character encoding, it behaves according to the
(transcoder i/o-decoding-error-transcoder)) specified error-handling mode. If it is ignore, the first byte
of the invalid encoding is ignored and decoding continues
An exception with this type is raised when one of the oper- with the next byte. If it is replace, the replacement char-
ations for textual output to a port encounters a character acter U+FFFD is injected into the data stream. Decoding
not supported by the codec of the specified transcoder. The subsequently continues with the next byte. If it is raise, a
transcoder field contains the transcoder specified with the continuable exception with condition type &i/o-decoding
operation. is raised. See the description of &i/o-decoding for details
on how to handle such an exception.
Exceptions of this type raised by the operations described
in this section are continuable. When such an exception is If a codec for an output port encounters a character it
raised, the port’s position is at the beginning of the invalid cannot encode, it behaves according to the specified error-
encoding. The exception handler must return a charac- handling mode. If it is ignore, the character is ignored and
ter or string representing the decoded text starting at the encoding continues after the encoding. If it is replace,
port’s current position, and the exception handler must an encoding-specific replacement character is emitted by
update the port’s position to point past the error. the transcoder, and decoding continues after the encoding.
This replacement character is U+FFFD for the Unicode
encodings capable of representing it, and the ? character
&i/o-encoding condition type for the Latin-1 encoding. If the mode is raise, an excep-
(i/o-encoding-error? obj ) procedure tion with condition type &i/o-encoding is raised. See the
(i/o-encoding-error-char condition) procedure description of &i/o-decoding for details on how to handle
(i/o-encoding-error-transcoder condition) such an exception.
procedure
This condition type could be defined by (make-transcoder codec eol-style handling-mode)
(define-condition-type &i/o-encoding &i/o-port procedure
i/o-encoding-error? (make-transcoder codec eol-style) procedure
(char i/o-encoding-error-char) (make-transcoder codec) procedure
(transcoder i/o-encoding-error-transcoder))
Codec must be a codec, eol-style, if present, an eol-style
symbol, and handling-mode, if present, an error-handling-
An exception with this type is raised when one of the oper- mode symbol. eol-style may be omitted, in which case it
ations for textual output to a port encounters a character defaults to the native end-of-line style of the underlying
not supported by the codec of the specified transcoder. platform. handling-mode may be omitted, in which case
The char field of the condition object contains the char- it defaults to raise. The result is a transcoder with the
acter that the operation was unable to encode, and the behavior specified by its arguments.
transcoder field contains the transcoder specified with the
operation. A transcoder returned by make-transcoder is equal in
the sense of eqv? to any other transcoder returned by
Exceptions of this type raised by the operations described make-transcoder, if and only if the code, eol-style, and
in this section are continuable. The handler, if it returns, handling-mode arguments are equal in the sense of eqv?.
is expected to output to the port an appropriate encoding
for the character that caused the error. The operation that
raised the exception continues after that character. (transcoder-codec transcoder ) procedure
(transcoder-eol-style transcoder ) procedure
(transcoder-error-handling-mode transcoder )
(error-handling-mode name) syntax procedure
If name is one of the hidentifieris ignore, raise, or These are accessors for transcoder objects; when applied
replace, then the result is the corresponding symbol. If to a transcoder returned by make-transcoder, they return
name is not one of these identifiers, the result the expres- the codec, eol-style, handling-mode arguments.
sion is implementation-dependent.
Rationale: Implementations may support error-handling
modes other than those listed. 15.3.4. Input and output ports
When part of a transcoder, an error-handling mode speci- The operations described in this section are common to
fies the behavior of a text I/O operation in the presence of input and output ports. A port may have an associ-
an encoding or decoding error: ated position that specifies a particular place within its
88 Revised5.91 Scheme
data sink or source as a byte count from the beginning already been closed. A closed port is still a port. The
of the sink or source, and operations for inspecting and unspecified value is returned.
setting it. (Ends of file do not count as bytes.) A
port may also have an associated transcoder that repre- (call-with-port port proc) procedure
sents a default text encoding associated with the port.
Note that the transcoder associated with a port does Proc must be a procedure that accepts a single argument.
not have any direct effect on the behavior of procedures The call-with-port procedure calls proc with port as an
that perform textual I/O except for get-output-string argument. If proc returns, then the port is closed automat-
and call-with-string-output-port. However, it can ically and the values returned by proc are returned. If proc
be passed to those procedures to specify that the text does not return, then the port is not closed automatically,
encoding or decoding should happen according to that unless it is possible to prove that the port will never again
transcoder. be used for a lookahead, get, or put operation.
Returns #t if the argument is a port, and returns #f oth- An input port allows reading an infinite sequence of bytes
erwise. punctuated by end of file objects. An input port connected
to a finite data source ends in an infinite sequence of end
of file objects. All of the procedures that perform textual
(port-transcoder port) procedure input accept a transcoder as an optional argument. If no
Returns the transcoder associated with port, if it has one, transcoder is supplied or the transcoder argument is #f,
or #f if no transcoder is associated with port. the input bytes are interpreted as UTF-8 with a platform-
specific end-of-line convention.
(lookahead-u8 input-port) procedure Reads from input-port, blocking as necessary, until the
The lookahead-u8 procedure is like get-u8, but it does complete encoding for a character is available from input-
not update input-port to point past the byte. port, or until the bytes that are available cannot be the pre-
fix of any valid encoding, or until an end of file is reached.
If a complete character is available before the next end
(get-bytes-n input-port k ) procedure of file, get-char returns that character, and it updates
Reads from input-port, blocking as necessary, until k bytes the input port to point past the bytes that encoded that
are available from input-port or until an end of file is character. If an end of file is reached before any bytes are
reached. If k or more bytes are available before an end of read, then get-char returns the end-of-file object.
file, get-bytes-n returns a bytes object of size k . If fewer
bytes are available before an end of file, get-bytes-n re- (lookahead-char input-port) procedure
turns a bytes object containing those bytes. In either case, (lookahead-char input-port transcoder ) procedure
the input port is updated to point just past the bytes read. The lookahead-char procedure is like get-char, but it
If an end of file is reached before any bytes are available, does not update input-port to point past the bytes that
get-bytes-n returns the end-of-file object. encode the character.
90 Revised5.91 Scheme
Note: With some of the standard transcoders described in end of file, decoding characters in the same manner as
this document, up to eight bytes of lookahead are required. get-string-n and get-string-n!.
Nonstandard transcoders may require even more lookahead.
If an end-of-line encoding or line separator is read, then
a string containing all of the text up to (but not includ-
(get-string-n input-port k ) procedure ing) the end-of-line encoding is returned, and the port is
(get-string-n input-port k transcoder ) procedure updated to point just past the end-of-line encoding or line
separator. If an end of file is encountered before any end-
Reads from input-port, blocking as necessary, until the en- of-line encoding is read, but some bytes have been read and
codings of k characters (including invalid encodings, if they decoded as characters, then a string containing those char-
don’t raise an exception) are available, or until an end of acters is returned. If an end of file is encountered before
file is reached. any bytes are read, then the end-of-file object is returned.
If k or more characters are read before end of file,
get-string-n returns a string consisting of those k char-
acters. If fewer characters are available before an end of
(get-datum input-port) procedure
file, but one or more characters can be read, get-string-n
(get-datum input-port transcoder ) procedure
returns a string containing those characters. In either case,
the input port is updated to point just past the data read. Reads an external representation from input-port and re-
If no bytes can be read before an end of file, then the end- turns the datum it represents. The get-datum procedure
of-file object is returned. returns the next datum parsable from the given input-port,
updating input-port to point exactly past the end of the ex-
ternal representation of the object.
(get-string-n! input-port string start count)
procedure Any hintertoken spacei (see section 3.2) in the input
(get-string-n! input-port string start count transcoder ) is first skipped. If an end of file occurs after the
procedure hintertoken spacei, the end of file object (see section 9.9)
is returned.
Start and count must be an exact, non-negative integer,
specifying the number of characters to be read. string must If a character inconsistent with an external representation
be a string with at least start + count characters. is encountered in the input, an exception with condition
types &lexical and &i/o-read is raised. Also, if the end
Reads from input-port in the same manner as of file is encountered after the beginning of an external rep-
get-string-n. If count or more characters are available resentation, but the external representation is incomplete
before an end of file, they are written into string starting and therefore not parsable, an exception with condition
at index start, and count is returned. If fewer characters types &lexical and &i/o-read is raised.
are available before an end of file, but one or more can be
read, then those characters are written into string starting
at index start, and the number of characters actually read 15.3.6. Output ports
is returned. If no characters can be read before an end of
file, then the end-of-file object is returned. An output port is a sink to which bytes are written. These
bytes may control external devices, or may produce files
and other objects that may subsequently be opened for
(get-string-all input-port) procedure input. The procedures in this section that perform textual
(get-string-all input-port transcoder ) procedure output accept a transcoder as an optional argument. If no
transcoder is supplied, the character(s) output is translated
Reads from input-port until an end of file, decoding
to UTF-8 with a platform-specific end-of-line convention.
characters in the same manner as get-string-n and
get-string-n!.
If data are available before the end of file, a string con- (output-port? obj ) procedure
taining all the text decoded from that data is returned. If Returns #t if the argument is an output port (or a com-
no data precede the end of file, the end-of-file object file bined input and output port), and returns #f otherwise.
object is returned.
(put-u8 output-port octet) procedure 15.3.7. Opening files for reading and writing
Writes octet to the output port and returns the unspecified
value.
(open-file-input/output-port filename) procedure
(open-file-input/output-port filename file-options)
(put-bytes output-port bytes) procedure procedure
(put-bytes output-port bytes start) procedure (open-file-input/output-port filename procedure
(put-bytes output-port bytes start count) procedure file-options buffer-mode)
Start and count must be non-negative exact integers that (open-file-input/output-port filename procedure
default to 0 and (bytes-length bytes) − start, respec- file-options buffer-mode transcoder )
tively. bytes must have a size of at least start + count. The Returns a single port that is both an input port and an
put-bytes procedure writes count bytes of the bytes ob- output port for the named file and options (which default
ject bytes, starting at index start, to the output port. The to (file-options)). buffer-mode optionally specifies the
unspecified value is returned. buffer mode of the port; it defaults to block.
The returned port supports the port-position and
(put-char output-port char ) procedure set-port-position! operations. The same port position
(put-char output-port char transcoder ) is used for both input and output.
If transcoder is specified, it becomes the transcoder asso-
Writes an encoding of char to the port. The unspecified ciated with the returned port.
value is returned.
(put-string output-port string) procedure 15.3.8. Ports from readers and writers
(put-string output-port string transcoder ) procedure
Writes an encoding of string to the port. The unspecified
value is returned. (open-reader-input-port reader ) procedure
(open-reader-input-port reader transcoder )
procedure
(put-string-n output-port string) procedure
Returns an input port connected to the reader reader . If
(put-string-n output-port string start) procedure
transcoder is specified, it becomes the transcoder associ-
(put-string-n output-port string start count)
ated with the returned port.
procedure
(put-string-n output-port string start count transcoder ) The returned port supports the port-position operation
procedure if and only if reader supports the reader-get-position
Start and count must be non-negative exact integers. operation. It supports the set-port-position! operation
string must have a length of at least start + count. start if and only if reader supports the reader-set-position!
defaults to 0. count defaults to (string-length bytes) − operation.
start. Writes the encoding of the count characters of string,
starting at index start, to the port. The unspecified value
is returned. (open-writer-output-port writer ) procedure
(open-writer-output-port writer buffer-mode)
procedure
(put-datum output-port datum) procedure (open-writer-output-port writer procedure
(put-datum output-port datum transcoder ) procedure buffer-mode transcoder )
Datum should be a datum value. The put-datum Returns an output port connected to the writer writer .
procedure writes an external representation of datum buffer-mode optionally specifies the buffer mode of the
to output-port. The specific external representation is port; it defaults to block. If transcoder is specified, it
implementation-dependent. becomes the transcoder associated with the returned port.
Note: The put-datum procedure merely writes the external The returned port supports the port-position operation
reprentation. If put-datum is used to write several subsequent if and only if writer supports the writer-get-position
external representations to an output port, care must be taken operation. It supports the set-port-position! operation
to delimit them properly so they can be read back in by subse- if and only if writer supports the writer-set-position!
quent calls to get-datum. operation.
15. I/O 93
with −π ≤ angle z ≤ π and angle z = b + 2πn for some This section specifies two kinds of operations on fixnums.
integer n. Operations whose names begin with fixnum perform
arithmetic modulo 2w . Operations whose names be-
With the one-argument version of log defined this way, the gin with fx perform integer arithmetic on their fixnum
values of the two-argument-version of log, sin−1 z, cos−1 z, arguments, but raise an exception with condition type
tan−1 z, and the two-argument version of tan−1 are accord- &implementation-restriction if the result is not a
ing to the following formulæ: fixnum.
log z Rationale: The operations whose names begin with fixnum im-
log z b =
log b plement arithmetic on a quotient ring of the integers, but their
p
sin−1 z = −i log(iz + 1 − z 2 ) results are not the same in every implementation because the
particular ring is parameterized by w. The operations whose
cos−1 z = π/2 − sin−1 z
names begin with fx do not have as nice a closure property,
tan−1 z = (log(1 + iz) − log(1 − iz))/(2i) and the arguments that cause them to raise an exception are
tan−1 x y = angle(x + yi) not the same in every implementation, but any results they
96 Revised5.91 Scheme
return without raising an exception are the same in all imple- (fixnum+ fx1 . . . ) procedure
mentations. (fixnum* fx1 . . . ) procedure
Some operations (e.g. fixnum< and fx<) behave the same These procedures return the unique fixnum that is con-
in both sets. gruent mod 2w to the sum or product of their arguments.
Rationale: Duplication of names reduces bias toward either
set, and saves programmers from having to remember which
names are supplied.
(fixnum- fx1 fx2 . . . ) procedure
This section uses fx , fx1 and fx2 as parameter names for (fixnum- fx ) procedure
arguments that must be fixnums.
With two or more arguments, this procedure returns the
unique fixnum that is congruent mod 2w to the difference of
16.3.1. Quotient-ring fixnum operations its arguments, associating to the left. With one argument,
however, it returns the the unique fixnum that is congruent
This section describes the (r6rs arithmetic fixnum) li- mod 2w to the additive inverse of its argument.
brary.
(fixnum-zero? fx ) procedure Returns the two fixnum results of the following computa-
tion:
(fixnum-positive? fx ) procedure
(fixnum-negative? fx ) procedure (let* ((s (+ fx1 fx2 fx3 ))
(fixnum-odd? fx ) procedure (s0 (mod0 s (expt 2 (fixnum-width))))
(fixnum-even? fx ) procedure (s1 (div0 s (expt 2 (fixnum-width)))))
(values s0 s1))
These numerical predicates test a fixnum for a particular
property, returning #t or #f. The five properties tested by Note: The results returned by the fixnum+/carry,
these procedures are: whether the number is zero, greater fixnum-/carry, and fixnum*/carry procedures depend upon
than zero, less than zero, odd, or even. the precision w, so there are no fx equivalents to these proce-
dures.
(fixnum-logical-shift-right fx1 fx2 ) procedure This section describes the (r6rs arithmetic fx) library.
Fx2 must be non-negative. The
fixnum-logical-shift-right procedure returns the (fixnum? obj ) procedure
result of the following computation:
(let* ((n fx1 )
This is the same as fixnum? in the (r6rs arithmetic
(shift fx2 ) fixnum) library.
(shifted
(fixnum-arithmetic-shift-right n shift)))
(let* ((mask-width (fixnum-width) procedure
(fixnum- (least-fixnum) procedure
(fixnum-width) (greatest-fixnum) procedure
(fixnum-mod shift (fixnum-width))))
(mask (fixnum-not These are the same as fixnum-width, least-fixnum, and
(fixnum-logical-shift-left greatest-fixnum in the (r6rs arithmetic fixnum) li-
-1 mask-width)))) brary, respectively.
(fixnum-and shifted mask)))
Note: The results of fixnum-logical-shift-left and (fx=? fx1 fx2 fx3 . . . ) procedure
fixnum-logical-shift-left can depend upon the precision w, (fx>? fx1 fx2 fx3 . . . ) procedure
so they have no fx equivalents. (fx<? fx1 fx2 fx3 . . . ) procedure
(fx>=? fx1 fx2 fx3 . . . ) procedure
(fixnum-rotate-bit-field fx1 fx2 fx3 fx4 ) procedure (fx<=? fx1 fx2 fx3 . . . ) procedure
Fx2 , fx3 , and fx4 must be non-negative. The These procedures perform the same operations as
fixnum-rotate-bit-field procedure returns the result of fixnum=?, fixnum>?, fixnum<?, fixnum>=?, and
the following computation: fixnum<=?, respectively.
(let* ((n fx1 )
(start fx2 )
(end fx3 ) (fxzero? fx ) procedure
(count fx4 ) (fxpositive? fx ) procedure
(width (fixnum- end start))) (fxnegative? fx ) procedure
(if (fixnum-positive? width) (fxodd? fx ) procedure
(let* ((count (fixnum-mod count width)) (fxeven? fx ) procedure
(field0
(fixnum-bit-field n start end)) These procedures perform the same operations as
(field1 fixnum-zero?, fixnum-positive?, fixnum-negative?,
(fixnum-logical-shift-left fixnum-odd?, and fixnum-even?, respectively.
16. Arithmetic 99
This section describes the (r6rs arithmetic flonum) li- Note: (flnegative? -0.0) must return #f, else it would lose
brary. the correspondence with (fl< -0.0 0.0), which is #f according
This section uses fl , fl1 and fl2 as parameter names for ar- to the IEEE standards.
guments that must be flonums, and ifl , ifl1 and ifl2 as pa-
rameter names for arguments that must be integer-valued
(flmax fl1 fl2 . . . ) procedure
flonums, i.e. flonums for which the integer-valued? pred-
(flmin fl1 fl2 . . . ) procedure
icate returns true.
These procedures return the maximum or minimum of their
arguments.
(flonum? obj ) procedure
Returns #t if obj is a flonum, and otherwise returns #f.
(fl+ fl1 . . . ) procedure
(fl* fl1 . . . ) procedure
(fl=? fl1 fl2 fl3 . . . ) procedure
(fl<? fl1 fl2 fl3 . . . ) procedure These procedures return the flonum sum or product of
(fl<=? fl1 fl2 fl3 . . . ) procedure their flonum arguments. In general, they should return
(fl>? fl1 fl2 fl3 . . . ) procedure the flonum that best approximates the mathematical sum
(fl>=? fl1 fl2 fl3 . . . ) procedure or product. (For implementations that represent flonums
as IEEE binary floating point numbers, the meaning of
These procedures return #t if their arguments are (respec-
“best” is reasonably well-defined by the IEEE standards.)
tively): equal, monotonically increasing, monotonically de-
creasing, monotonically nondecreasing, or monotonically (fl+ +inf.0 -inf.0) =⇒ +nan.0
nonincreasing, #f otherwise. These predicates are required (fl+ +nan.0 fl ) =⇒ +nan.0
to be transitive. (fl* +nan.0 fl ) =⇒ +nan.0
16. Arithmetic 101
result for the given arguments, the result may be a NaN, These types describe that a program has executed an arith-
or may be some meaningless flonum. metic operations that is specified to return an infinity or a
NaN, respectively, on a Scheme implementation that is not
Implementations that use IEEE binary floating point arith-
able to represent the infinity or NaN. (See section 16.1.)
metic are encouraged to follow the relevant standards for
these procedures.
(fixnum->flonum fx ) procedure
(flexp +inf.0) =⇒ +inf.0
(flexp -inf.0) =⇒ 0.0 Returns a flonum that is numerically closest to fx .
(fllog +inf.0) =⇒ +inf.0 Note: The result of this procedure may not be numerically
(fllog 0.0) =⇒ -inf.0
equal to fx , because the fixnum precision may be greater than
(fllog -0.0) =⇒ unspecified
the flonum precision.
; if -0.0 is distinguished
(fllog -inf.0) =⇒ +nan.0
(flatan -inf.0)
=⇒ -1.5707963267948965 16.5. Exact arithmetic
; approximately
(flatan +inf.0) This section describes the (r6rs arithmetic exact) li-
=⇒ 1.5707963267948965 brary.
; approximately
The exact arithmetic provides generic operations on exact
numbers; these operations correspond to their mathemat-
ical counterparts. The exact numbers include rationals of
(flsqrt fl ) procedure arbitrary precision, and exact rectangular complex num-
Returns the principal square root of fl . For a negative ar- bers. A rational number with a denominator of 1 is in-
gument, the result may be a NaN, or may be some mean- distinguishable from its numerator. An exact rectangular
ingless flonum. complex number with a zero imaginary part is indistin-
guishable from its real part.
(flsqrt +inf.0) =⇒ +inf.0
(exact-number? ex ) procedure
(exact-complex? ex ) procedure
(flexpt fl1 fl2 ) procedure (exact-rational? ex ) procedure
Returns fl1 raised to the power fl2 . fl1 should be non- (exact-integer? ex ) procedure
negative; if fl1 is negative, then the result may be a NaN, These numerical type predicates can be applied to any kind
or may be some meaningless flonum. If fl1 is zero, then the of argument, including non-numbers. They return #t if the
result is zero. For positive fl 1 , object is an exact number of the named type, and otherwise
return #f. In general, if a type predicate is true of a number
fl then all higher type predicates are also true of that number.
fl 1 2 = efl 2 log fl 1 Consequently, if a type predicate is false of a number, then
all lower type predicates are also false of that number.
This section uses ex , ex1 , ex2 , and ex3 as parameter names
for arguments that must be exact complex numbers, ef ,
&no-infinities condition type ef1 , ef2 , and ef3 as parameter names for arguments that
(no-infinities? obj ) procedure must be exact rational numbers, and ei , ei1 , ei2 , and ei3
&no-nans condition type as parameter names that must be exact integers.
(no-nans? obj ) procedure
These condition types could be defined by the following (exact=? ex1 ex2 ex3 . . . ) procedure
code: (exact>? ef1 ef2 ef3 . . . ) procedure
(exact<? ef1 ef2 ef3 . . . ) procedure
(define-condition-type &no-infinities (exact>=? ef1 ef2 ef3 . . . ) procedure
&implementation-restriction (exact<=? ef1 ef2 ef3 . . . ) procedure
no-infinities?)
These procedures return #t if their arguments are (respec-
(define-condition-type &no-nans tively): equal, monotonically increasing, monotonically de-
&implementation-restriction creasing, monotonically nondecreasing, or monotonically
no-nans?) nonincreasing #f otherwise.
16. Arithmetic 103
(exact-numerator ef ) procedure
(exact-max ef1 ef2 . . . ) procedure (exact-denominator ef ) procedure
(exact-min ef1 ef2 . . . ) procedure
These procedures return the numerator or denominator of
These procedures return the maximum or minimum of their their argument. The result is computed as if the argument
arguments. were represented as a fraction in lowest terms. The denom-
inator is always positive. The denominator of 0 is defined
(exact+ ex1 ex2 . . . ) procedure to be 1.
(exact* ex1 ex2 . . . ) procedure
These procedures return the sum or product of their argu- (exact-floor ef ) procedure
ments. (exact-ceiling ef ) procedure
(exact-truncate ef ) procedure
(exact- ex1 ex2 . . . ) procedure (exact-round ef ) procedure
(exact- ex ) procedure These procedures return exact integers. The exact-floor
(exact/ ex1 ex2 . . . ) procedure procedure returns the largest integer not larger than ef .
(exact/ ex ) procedure The exact-ceiling procedure returns the smallest inte-
With two or more arguments, these procedures return the ger not smaller than ef . The exact-truncate procedure
difference or quotient of their arguments, associating to returns the integer closest to ef whose absolute value is not
the left. With one argument, however, they return the larger than the absolute value of ef . The exact-round pro-
additive or multiplicative inverse of their argument. The cedure returns the closest integer to ef , rounding to even
exact/ procedure raises an exception with condition type when ef is halfway between two integers.
&contract if a divisor is 0.
(exact-expt ef1 ei2 ) procedure
(exact-abs ef ) procedure Returns ef1 raised to the power ei2 . 0ei is 1 if ei = 0 and 0
Returns the absolute value of ef . if ei is positive. If ef1 is zero and ei2 is negative, this pro-
cedure raises an exception with condition type &contract.
(exact-div+mod ef1 ef2 ) procedure
(exact-div ef1 ef2 ) procedure
(exact-mod ef1 ef2 ) procedure (exact-make-rectangular ef1 ef2 ) procedure
(exact-div0+mod0 ef1 ef2 ) procedure (exact-real-part ex ) procedure
(exact-div0 ef1 ef2 ) procedure (exact-imag-part ex ) procedure
(exact-mod0 ef1 ef2 ) procedure The arguments of exact-make-rectangular must be ex-
Ef2 must be nonzero. These procedures implement act rationals. Suppose ex is a complex number such that
number-theoretic integer division and return the results
of the corresponding mathematical operations specified in ex = ef1 + ef2 i.
section 16.2.1.
Then:
(exact-div ef1 ef2 ) =⇒ ef1 div ef2
(exact-mod ef1 ef2 ) =⇒ ef1 mod ef2 (exact-make-rectangular ef1 ef2 )
(exact-div+mod ef1 ef2 ) =⇒ ex
=⇒ ef1 div ef2 , ef1 mod ef2 (exact-real-part ex ) =⇒ ef1
; two return values (exact-imag-part ex ) =⇒ ef2
104 Revised5.91 Scheme
These procedures return the exact integer that is the bit- (let* ((mask (exact-arithmetic-shift-left 1 ei2 )))
(exact-if mask
wise “and,” “inclusive or,” or “exclusive or” of the two’s
(exact-arithmetic-shift-left ei3 ei2 )
complement representations of their arguments. If they ei1 ))
are passed only one argument, they return that argument.
If they are passed no arguments, they return the integer
(either −1 or 0) that acts as identity for the operation. (exact-bit-field ei1 ei2 ei3 ) procedure
Ei2 and ei3 must be non-negative, and ei2 must be less
(exact-if ei1 ei2 ei3 ) procedure than or equal to ei3 . This procedure returns the result of
the following computation:
Returns the exact integer that is the result of the following
computation: (let* ((mask
(exact-not
(exact-ior (exact-and ei1 ei2 ) (exact-arithmetic-shift-left -1 ei3 ))))
(exact-and (exact-not ei1 ) ei3 )) (exact-arithmetic-shift-right
(exact-and ei1 mask)
ei2 ))
(exact-bit-count ei ) procedure
If ei is non-negative, this procedure returns the number of
1 bits in the two’s complement representation of ei . Other- (exact-copy-bit-field ei1 ei2 ei3 ei4 ) procedure
wise it returns the number of 0 bits in the two’s complement Ei2 and ei3 must be non-negative, and ei2 must be less than
representation of ei . or equal to ei3 . The exact-copy-bit-field procedure
returns the result of the following computation:
(exact-length ei ) procedure (let* ((to ei1 )
(start ei2 )
These procedures return the exact integer that is the result (end ei3 )
of the following computation: (from ei4 )
(do ((result 0 (+ result 1)) (mask1
(bits (if (exact-negative? ei) (exact-arithmetic-shift-left -1 start))
(exact-not ei) (mask2
ei) (exact-not
(exact-arithmetic-shift bits -1))) (exact-arithmetic-shift-left -1 end)))
((exact-zero? bits) (mask (exact-and mask1 mask2)))
result)) (exact-if mask
(exact-arithmetic-shift-left from
start)
(exact-first-bit-set ei ) procedure to))
Returns the index of the least significant 1 bit in the two’s
complement representation of ei . If ei is 0, then −1 is
(exact-arithmetic-shift ei1 ei2 ) procedure
returned.
Returns the exact integer result of the following computa-
(exact-first-bit-set 0) =⇒ -1
tion:
(exact-first-bit-set 1) =⇒ 0
(exact-first-bit-set -4) =⇒ 2 (exact-floor (* ei1 (expt 2 ei2 )))
16. Arithmetic 105
call. A reference to an identifier introduced into to the identifier, i.e., the outermost substitution in the
the output of a transformer refers to the closest wrap whose name and marks match the name and marks
enclosing binding for the introduced identifier or, recorded in the substitution. The name matches if it is the
if it appears outside of any enclosing binding for same name (if using symbols, then by eq?), and the marks
the introduced identifier, the closest enclosing lex- match if the marks recorded with the substitution are the
ical binding where the identifier appears (within same as those that appear below the substitution in the
a syntax htemplatei) inside the transformer body wrap, i.e., those that were applied before the substitution.
or one of the helpers it calls. Marks applied after a substitution, i.e., appear over the
substitution in the wrap, are not relevant and are ignored.
Explicit captures are handled via datum->syntax; see sec- An algebra that defines how marks and substitutions work
tion 17.6. more precisely is given in section 2.4 of Oscar Waddell’s
Operationally, the expander can maintain hygiene with the PhD thesis [52].
help of marks and substitutions. Marks are applied selec-
tively by the expander to the output of each transformer
it invokes, and substitutions are applied to the portions 17.2. Syntax objects
of each binding form that are supposed to be within the
scope of the bound identifiers. Marks are used to distin- A syntax object is a representation of a Scheme form that
guish like-named identifiers that are introduced at different contains contextual information about the form in addi-
times (either present in the source or introduced into the tion to its structure. This contextual information is used
output of a particular transformer call), and substitutions by the expander to maintain lexical scoping and may also
are used to map identifiers to their expand-time values. be used by an implementation to maintain source-object
correlation.
Each time the expander encounters a macro use, it ap-
plies an antimark to the input form, invokes the associ- Syntax objects may be wrapped or unwrapped. A wrapped
ated transformer, then applies a fresh mark to the output. syntax object (section 17.1), consists of a wrap (sec-
Marks and antimarks cancel, so the portions of the input tion 17.1) and some internal representation of a Scheme
that appear in the output are effectively left unmarked, form. (The internal representation is unspecified, but is
while the portions of the output that are introduced are typically a datum value or datum value annotated with
marked with the fresh mark. source information.) A wrapped syntax object represent-
ing an identifier is itself referred to as an identifier; thus,
Each time the expander encounters a binding form it cre- the term identifier may refer either to the syntactic entity
ates a set of substitutions, each mapping one of the (pos- (symbol, variable, or keyword) or to the concrete represen-
sibly marked) bound identifiers to information about the tation of the syntactic entity as a syntax object. Wrapped
binding. (For a lambda expression, the expander might syntax objects are distinct from other types of values.
map each bound identifier to a representation of the for-
mal parameter in the output of the expander. For a An unwrapped syntax object is one that is unwrapped,
let-syntax form, the expander might map each bound fully or partially, i.e., whose outer layers consist of lists
identifier to the associated transformer.) These substitu- and vectors and whose leaves are either wrapped syntax
tions are applied to the portions of the input form in which objects or nonsymbol values.
the binding is supposed to be visible. The term syntax object is used in this document to refer
Marks and substitutions together form a wrap that is lay- to a syntax object that is either wrapped or unwrapped.
ered on the form being processed by the expander and More formally, a syntax object is:
pushed down toward the leaves as necessary. A wrapped
form is referred to as a wrapped syntax object. Ultimately, • a pair or list of syntax objects,
the wrap may rest on a leaf that represents an identifier, in
which case the wrapped syntax object is referred to more • a vector of syntax objects,
precisely as an identifier. An identifier contains a name
• a nonlist, nonvector, nonsymbol value, or
along with the wrap. (Names are typically represented by
symbols.) • a wrapped syntax object.
When a substitution is created to map an identifier to an
expand-time value, the substitution records the name of The distinction between the terms “syntax object” and
the identifier and the set of marks that have been ap- “wrapped syntax object” is important. For example, when
plied to that identifier, along with the associated expand- invoked by the expander, a transformer (section 17.3) must
time value. The expander resolves identifier references by accept a wrapped syntax object but may return any syntax
looking for the latest matching substitution to be applied object, including an unwrapped syntax object.
17. syntax-case 109
(syntax-case hexpressioni (hliterali ...) hclausei ...) • P is of the form (P1 ... Pn . Px ) and F is a list
syntax or improper list of n or more elements whose first n
elements match P1 through Pn and whose nth cdr
Syntax: Each hliterali must be an identifier. Each hclausei matches Px .
must take one of the following two forms.
(hpatterni houtput expressioni) • P is of the form (P1 ... Pk Pe hellipsisi Pm+1 ...
(hpatterni hfenderi houtput expressioni) Pn ), where hellipsisi is the identifier ... and F is a
proper list of n elements whose first k elements match
hFenderi and houtput expressioni must be hexpressionis. P1 through Pk , whose next m−k elements each match
A hpatterni is an identifier, constant, or one of the follow- Pe , and whose remaining n − m elements match Pm+1
ing. through Pn .
110 Revised5.91 Scheme
• P is of the form (P1 ... Pk Pe hellipsisi Pm+1 ... htemplatei are inserted into htemplatei, (2) contextual in-
Pn . Px ), where hellipsisi is the identifier ... and formation associated both with the input and with the tem-
F is a list or improper list of n elements whose first plate is retained in the output to support lexical scoping,
k elements match P1 through Pk , whose next m − k and (3) the value of a syntax expression is a syntax object.
elements each match Pe , whose next n − m elements A htemplatei is a pattern variable, an identifier that is not
match Pm+1 through Pn , and whose nth and final cdr a pattern variable, a pattern datum, or one of the following.
matches Px .
(hsubtemplatei ...)
• P is of the form #(P1 ... Pn ) and F is a vector of n (hsubtemplatei ... . htemplatei)
elements that match P1 through Pn . #(hsubtemplatei ...)
The input subforms inserted in place of the pattern vari- (define p (cons 4 5))
ables are wrapped if and only if the corresponding input (define-syntax p.car
subforms are wrapped. (make-variable-transformer
(lambda (x)
The following definitions of or illustrate syntax-case and (syntax-case x (set!)
syntax. The second is equivalent to the first but uses the [(set! e) #’(set-car! p e)]
the #’ prefix instead of the full syntax form. [( . rest) #’((car p) . rest)]
[ #’(car p)]))))
(define-syntax or
(set! p.car 15)
(lambda (x)
p.car =⇒ 15
(syntax-case x ()
p =⇒ (15 5)
[( ) (syntax #f)]
[( e) (syntax e)] A derived identifier-syntax form that simplifies the def-
[( e1 e2 e3 ...) inition of identifier macros is described in section 17.8.
(syntax (let ([t e1])
(if t t (or e2 e3 ...))))])))
17.5. Identifier predicates
(define-syntax or
(lambda (x)
(syntax-case x ()
[( ) #’#f] (identifier? obj ) procedure
[( e) #’e]
Returns #t if obj is an identifier, i.e., a syntax object rep-
[( e1 e2 e3 ...)
resenting an identifier, and #f otherwise.
#’(let ([t e1])
(if t t (or e2 e3 ...)))]))) The identifier? procedure is often used within a fender
to verify that certain subforms of an input form are iden-
(define-syntax case tifiers, as in the definition of rec, which creates self-
(lambda (x) contained recursive objects, below.
(syntax-case x (else)
[( e0 [(k ...) e1 e2 ...] ... (define-syntax rec
[else else-e1 else-e2 ...]) (lambda (x)
#’(let ([t e0]) (syntax-case x ()
(cond [( x e)
[(memv t ’(k ...)) e1 e2 ...] (identifier? #’x)
... #’(letrec ([x e]) x)])))
[else else-e1 else-e2 ...]))]
[( e0 [(ka ...) e1a e2a ...] (map (rec fact
[(kb ...) e1b e2b ...] ...) (lambda (n)
#’(let ([t e0]) (if (= n 0)
(cond 1
[(memv t ’(ka ...)) e1a e2a ...] (* n (fact (- n 1))))))
[(memv t ’(kb ...)) e1b e2b ...] ’(1 2 3 4 5))
...))]))) =⇒ (1 2 6 24 120)
(free-identifier=? id1 id2 ) procedure The following definition of case is equivalent to the one
in section 17.4. Rather than including else in the literals
Id1 and id2 must be identifiers. The free-identifier=? list as before, this version explicitly tests for else using
procedure returns #t if and only if the two identifiers would free-identifier=?.
resolve to the same binding if both were to appear in
the output of a transformer outside of any bindings in- (define-syntax case
(lambda (x)
serted by the transformer. (If neither of two like-named
(syntax-case x ()
identifiers resolves to a binding, i.e., both are unbound, [( e0 [(k ...) e1 e2 ...] ...
they are considered to resolve to the same binding.) Op- [else-key else-e1 else-e2 ...])
erationally, two identifiers are considered equivalent by (and (identifier? #’else-key)
free-identifier=? if and only the topmost matching sub- (free-identifier=? #’else-key #’else))
stitution for each maps to the same binding (section 17.1) #’(let ([t e0])
or the identifiers have the same name and no matching (cond
substitution. [(memv t ’(k ...)) e1 e2 ...]
...
syntax-case and syntax-rules use free-identifier=? [else else-e1 else-e2 ...]))]
to compare identifiers listed in the literals list against input [( e0 [(ka ...) e1a e2a ...]
identifiers. [(kb ...) e1b e2b ...] ...)
#’(let ([t e0])
The following definition of unnamed let uses
(cond
bound-identifier=? to detect duplicate identifiers. [(memv t ’(ka ...)) e1a e2a ...]
(define-syntax let [(memv t ’(kb ...)) e1b e2b ...]
(lambda (x) ...))])))
(define unique-ids?
(lambda (ls) With either definition of case, else is not recognized as an
(or (null? ls)
auxiliary keyword if an enclosing lexical binding for else
(and (let notmem?
exists. For example,
([x (car ls)] [ls (cdr ls)])
(or (null? ls) (let ([else #f])
(and (not (bound-identifier=? (case 0 [else (write "oops")]))
x (car ls))) =⇒ &syntax exception
(notmem? x (cdr ls)))))
(unique-ids? (cdr ls)))))) since else is bound lexically and is therefore not the same
(syntax-case x () else that appears in the definition of case.
[( ((i v) ...) e1 e2 ...)
(unique-ids? #’(i ...))
#’((lambda (i ...) e1 e2 ...) v ...)]))) 17.6. Syntax-object and datum conversions
the variable break would not be visible in e .... 17.7. Generating lists of temporaries
The datum argument datum may also represent an arbi-
trary Scheme form, as demonstrated by the following defi- Transformers can introduce a fixed number of identifiers
nition of include. into their output simply by naming each identifier. In
114 Revised5.91 Scheme
some cases, however, the number of identifiers to be in- Semantics: When a keyword is bound to a transformer
troduced depends upon some characteristic of the input produced by the first form of identifier-syntax, refer-
expression. A straightforward definition of letrec, for ences to the keyword within the scope of the binding are
example, requires as many temporary identifiers as there replaced by htemplatei.
are binding pairs in the input expression. The procedure
(define p (cons 4 5))
generate-temporaries is used to construct lists of tem-
(define-syntax p.car (identifier-syntax (car p)))
porary identifiers. p.car =⇒ 4
(set! p.car 15) =⇒ &syntax exception
(generate-temporaries l ) procedure
The second, more general, form of identifier-syntax
L must be be a list or syntax object representing a list- permits the transformer to determine what happens when
structured form; its contents are not important. The num- set! is used. In this case, uses of the identifier by itself are
ber of temporaries generated is the number of elements in l . replaced by htemplate1 i, and uses of set! with the identi-
Each temporary is guaranteed to be unique, i.e., different fier are replaced by htemplate2 i.
from all other identifiers.
(define p (cons 4 5))
A definition of letrec that uses generate-temporaries (define-syntax p.car
is shown below. (identifier-syntax
[ (car p)]
[(set! e) (set-car! p e)]))
(define-syntax letrec
(set! p.car 15)
(lambda (x)
p.car =⇒ 15
(syntax-case x ()
p =⇒ (15 5)
(( ((i v) ...) e1 e2 ...)
(with-syntax The identifier-syntax form may be defined in terms of
(((t ...) syntax-case, syntax, and make-variable-transformer
(generate-temporaries (syntax (i ...))))) as follows.
(syntax (let ((i #f) ...)
(let ((t v) ...) (define-syntax identifier-syntax
(set! i t) ... (syntax-rules (set!)
(let () e1 e2 ...))))))))) [( e)
(lambda (x)
(syntax-case x ()
Any transformer that uses generate-temporaries in this [id (identifier? #’id) #’e]
fashion can be rewritten to avoid using it, albeit with a loss [( x (... ...)) #’(e x (... ...))]))]
of clarity. The trick is to use a recursively defined inter- [( (id exp1) ((set! var val) exp2))
mediate form that generates one temporary per expansion (and (identifier? #’id) (identifier? #’var))
step and completes the expansion after enough temporaries (make-variable-transformer
have been generated. See the definition for letrec in ap- (lambda (x)
pendix B. (syntax-case x (set!)
[(set! var val) #’exp2]
[(id x (... ...)) #’(exp1 x (... ...))]
17.8. Derived forms and procedures [id (identifier? #’id) #’exp1])))]))
The with-syntax form may be defined in terms of of unsyntax and unsyntax-splicing are valid only within
syntax-case as follows. quasisyntax expressions.
(define-syntax with-syntax A quasisyntax expression may be nested, with each
(lambda (x) quasisyntax introducing a new level of syntax quota-
(syntax-case x () tion and each unsyntax or unsyntax-splicing taking
(( ((p e0) ...) e1 e2 ...) away a level of quotation. An expression nested within
(syntax (syntax-case (list e0 ...) () n quasisyntax expressions must be within n unsyntax or
((p ...) (let () e1 e2 ...)))))))) unsyntax-splicing expressions to be evaluated.
The following definition of cond demonstrates the use of The quasisyntax keyword can be used in place of
with-syntax to support transformers that employ recur- with-syntax in many cases. For example, the definition of
sion internally to construct their output. It handles all case shown under the description of with-syntax above
cond clause variations and takes care to produce one-armed can be rewritten using quasisyntax as follows.
if expressions where appropriate. (define-syntax case
(lambda (x)
(define-syntax cond
(syntax-case x ()
(lambda (x)
[( e c1 c2 ...)
(syntax-case x ()
#`(let ([t e])
[( c1 c2 ...)
#,(let f ([c1 #’c1] [cmore #’(c2 ...)])
(let f ([c1 #’c1] [c2* #’(c2 ...)])
(if (null? cmore)
(syntax-case c2* ()
(syntax-case c1 (else)
[()
[(else e1 e2 ...)
(syntax-case c1 (else =>)
#’(begin e1 e2 ...)]
[(else e1 e2 ...) #’(begin e1 e2 ...)]
[((k ...) e1 e2 ...)
[(e0) #’(let ([t e0]) (if t t))]
#’(if (memv t ’(k ...))
[(e0 => e1)
(begin e1 e2 ...))])
#’(let ([t e0]) (if t (e1 t)))]
(syntax-case c1 ()
[(e0 e1 e2 ...)
[((k ...) e1 e2 ...)
#’(if e0 (begin e1 e2 ...))])]
#`(if (memv t ’(k ...))
[(c2 c3 ...)
(begin e1 e2 ...)
(with-syntax ([rest (f #’c2 #’(c3 ...))])
#,(f (car cmore)
(syntax-case c1 (=>)
(cdr cmore)))]))))])))
[(e0) #’(let ([t e0]) (if t t rest))]
[(e0 => e1)
#’(let ([t e0]) (if t (e1 t) rest))] Uses of unsyntax and unsyntax-splicing with zero or
[(e0 e1 e2 ...) more than one subform are valid only in splicing (list or
#’(if e0 vector) contexts. (unsyntax template ...) is equivalent
(begin e1 e2 ...) to (unsyntax template) ..., and (unsyntax-splicing
rest)]))]))]))) template ...) is equivalent to (unsyntax-splicing
template) .... These forms are primarily useful as inter-
mediate forms in the output of the quasisyntax expander.
(quasisyntax htemplatei) syntax Note: Uses of unsyntax and unsyntax-splicing with zero
or more than one subform enable certain idioms [4], such as
Note: #`htemplatei is equivalent to (quasisyntax
#,@#,@, which has the effect of a doubly indirect splicing when
htemplatei), #,htemplatei is equivalent to (unsyntax
used within a doubly nested and doubly evaluated quasisyntax
htemplatei), and #,@htemplatei is equivalent to
expression, as with the nested quasiquote examples shown in
(unsyntax-splicing htemplatei).
section 9.19.
The quasisyntax form is similar to syntax, but it allows Note: Any syntax-rules form can be expressed with
parts of the quoted text to be evaluated, in a manner sim- syntax-case by making the lambda expression and syntax ex-
ilar to the operation of quasiquote (section 9.19). pressions explicit, and syntax-rules may be defined in terms
of syntax-case as follows.
Within a quasisyntax template, subforms of unsyntax
(define-syntax syntax-rules
and unsyntax-splicing forms are evaluated, and every-
(lambda (x)
thing else is treated as ordinary template material, as (syntax-case x ()
with syntax. The value of each unsyntax subform is [( (k ...) [( . p) f ... t] ...)
inserted into the output in place of the unsyntax form, #’(lambda (x)
while the value of each unsyntax-splicing subform is (syntax-case x (k ...)
spliced into the surrounding list or vector structure. Uses [( . p) f ... #’t] ...))])))
116 Revised5.91 Scheme
A more robust implementation would verify that the literals and must be compatible with the equivalence function,
hliterali ... are all identifiers, that the first position of each which is a procedure that accepts two keys and returns
pattern is an identifier, and that at most one fender is present true if they are equivalent, otherwise returns #f. Stan-
in each clause. dard hash tables for arbitrary objects based on the eq?
and eqv? predicates (see section 9.6) are provided. Also,
standard hash functions for several types are provided.
17.9. Syntax violations
This section uses the hash-table parameter name for argu-
ments that must be hash tables, and the key parameter
name for arguments that must be hash-table keys.
(syntax-violation who message form) procedure
(syntax-violation who message form subform)
procedure 18.1. Constructors
Name must be #f or a string or a symbol. Message must
be a string. Form must be a syntax object or a datum
value. Subform must be a syntax object or a datum value. (make-eq-hash-table) procedure
The syntax-violation procedure raises an exception, re- (make-eq-hash-table k ) procedure
porting a syntax violation. The who argument should de- Returns a newly allocated mutable hash table that accepts
scribe the macro transformer that detected the exception. arbitrary objects as keys, and compares those keys with
The message argument should describe the violation. The eq?. If an argument is given, the initial capacity of the
form argument is the erroneous source syntax object or a hash table is set to approximately k elements.
datum value representing a form. The optional subform
argument is a syntax object or datum value representing a
form that more precisely locates the violation. (make-eqv-hash-table) procedure
(make-eqv-hash-table k ) procedure
If who is #f, syntax-violation attempts to infer an ap-
propriate value for the condition object (see below) as fol- Returns a newly allocated mutable hash table that accepts
lows: When form is either an identifier or a list-structured arbitrary objects as keys, and compares those keys with
syntax object containing an identifier as its first element, eqv?. If an argument is given, the initial capacity of the
then the inferred value is the identifier’s symbol. Other- hash table is set to approximately k elements.
wise, no value for who is provided as part of the condition
object. (make-hash-table hash-function equiv ) procedure
The condition object provided with the exception (see (make-hash-table hash-function equiv k ) procedure
chapter 14) has the following condition types: Hash-function and equiv must be procedures.
Hash-function will be called by other procedures de-
• If who is not #f or can be inferred, the condition has scribed in this chapter with a key as argument, and
condition type &who, with who as the value of the who must return a non-negative exact integer. Equiv will
field. In that case, who should identify the procedure be called by other procedures described in this chapter
or entity that detected the exception. If it is #f, the with two keys as arguments. The make-hash-table
condition does not have condition type &who. procedure returns a newly allocated mutable hash table
using hash-function as the hash function and equiv as
• The condition has condition type &message, with
the equivalence function used to compare keys. If a third
message as the value of the message field.
argument is given, the initial capacity of the hash table is
• The condition has condition type &syntax with form set to approximately k elements.
as the value of the form field, and subform as the value Both the hash function hash-function and the equivalence
of the subform field. If subform is not provided, the function equiv should behave like pure functions on the do-
value of the subform field is #f. main of keys. For example, the string-hash and string=?
procedures are permissible only if all keys are strings and
the contents of those strings are never changed so long as
18. Hash tables any of them continue to serve as a key in the hash table.
The (r6rs hash-tables) library provides hash tables. A Furthermore any pair of values for which the equivalence
hash table is a data structure that associates keys with val- function equiv returns true should be hashed to the same
ues. Any object can be used as a key, provided a hash exact integers by hash-function.
function and a suitable equivalence function is available. A Note: Hash tables are allowed to cache the results of calling
hash function is a procedure that maps keys to integers, the hash function and equivalence function, so programs cannot
18. Hash tables 117
rely on the hash function being called for every lookup or up- (hash-table-set!
date. Furthermore any hash-table operation may call the hash hash-table key
function more than once. (proc (hash-table-ref
hash-table key default)))
Rationale: Hash-table lookups are often followed by updates,
so caching may improve performance. Hash tables are free to
change their internal representation at any time, which may
result in many calls to the hash function. (hash-table-fold proc hash-table init) procedure
Proc must be a procedure that takes three arguments.
For every association in hash-table, hash-table-fold calls
18.2. Procedures proc with the association key, the association value, and an
accumulated value as arguments. The accumulated value
is init for the first invocation of proc, and for subsequent
(hash-table? hash-table) procedure invocations of proc, it is the return value of the previous
Returns #t if hash-table is a hash table, otherwise returns invocation of proc. The order of the calls to proc is indeter-
#f. minate. The return value of hash-table-fold is the value
of the last invocation of proc. If any side effect is performed
on the hash table while a hash-table-fold operation is
(hash-table-size hash-table) procedure in progress, then the behavior of hash-table-fold is un-
Returns the number of keys contained in hash-table as an specified.
exact integer.
(hash-table-copy hash-table) procedure
(hash-table-ref hash-table key default) procedure (hash-table-copy hash-table immutable) procedure
Returns the value in hash-table associated with key. If Returns a copy of hash-table. If the immutable argument is
hash-table does not contain an association for key, then provided and is true, the returned hash table is immutable;
default is returned. otherwise it is mutable.
Rationale: Hash table references may be less expensive with
(hash-table-set! hash-table key obj ) procedure immutable hash tables. Also, a library may choose to export a
Changes hash-table to associate key with obj , adding a hash table which cannot be changed by clients.
new association or replacing any existing association for
key, and returns the unspecified value. (hash-table-clear! hash-table) procedure
(hash-table-clear! hash-table k ) procedure
(hash-table-delete! hash-table key) procedure Removes all associations from hash-table and returns the
Removes any association for key within hash-table, and unspecified value.
returns the unspecified value. If a second argument is given, the current capacity of the
hash table is reset to approximately k elements.
(hash-table-contains? hash-table key) procedure
Returns #t if hash-table contains an association for key, (hash-table-keys hash-table) procedure
otherwise returns #f. Returns a list of all keys in hash-table. The order of the
list is unspecified. Equivalent to:
(hash-table-update! hash-table key proc default) (hash-table-fold (lambda (k v a) (cons k a))
procedure hash-table
’())
Proc must be a procedure that takes a single argument.
The hash-table-update! procedure applies proc to the
value in hash-table associated with key, or to default if
(hash-table-values hash-table) procedure
hash-table does not contain an association for key. The
hash-table is then changed to associate key with the result Returns a list of all values in hash-table. The order of the
of proc. list is unspecified. Equivalent to:
The behavior of hash-table-update! is equivalent to the (hash-table-fold (lambda (k v a) (cons v a))
following code, but may be implemented more efficiently in hash-table
cases where the implementation can avoid multiple lookups ’())
of the same key:
118 Revised5.91 Scheme
(define-enumeration htype-namei syntax hexpressionis are evaluated in order, and the result(s) of
(hsymboli . . . ) the last hexpressioni is(are) returned as the result(s) of the
hconstructor-syntaxi) entire when expression. Otherwise, the when expression
The define-enumeration form defines an enumeration evaluates to the unspecified value. An unless expression
type and provides two macros for constructing its mem- is evaluated by evaluating the htesti expression. If htesti
bers and sets of its members. evaluates to false, the remaining hexpressionis are evalu-
ated in order, and the result(s) of the last hexpressioni
A define-enumeration form is a definition and can appear is(are) returned as the result(s) of the entire unless ex-
anywhere any other hdefinitioni can appear. pression. Otherwise, the unless expression evaluates to
hType-namei is an identifier that is bound as a syntactic the unspecified value.
keyword; hsymboli . . . are the symbols that comprise the
(when (> 3 2) ’greater) =⇒ greater
universe of the enumeration (in order). (when (< 3 2) ’greater) =⇒ the unspecified value
(htype-namei hsymboli) checks at macro-expansion time (unless (> 3 2) ’less) =⇒ the unspecified value
whether hsymboli is in the universe associated with (unless (< 3 2) ’less) =⇒ less
htype-namei. If it is, then (htype-namei hsymboli) is
equivalent to hsymboli. It is a syntax violation if it is not. The when and unless expressions are derived forms. They
hConstructor-syntaxi is an identifier that is bound to a could be defined in terms of base library forms by the fol-
macro that, given any finite sequence of the symbols in the lowing macros:
universe, possibly with duplicates, expands into an expres-
(define-syntax when
sion that evaluates to the enumeration set of those symbols. (syntax-rules ()
(hconstructor-syntaxi hsymboli . . . ) checks at macro- ((when test result1 result2 ...)
expansion time whether every hsymboli . . . is in the uni- (if test
verse associated with htype-namei. It is a syntax violation (begin result1 result2 ...)))))
if one or more is not. Otherwise
(hconstructor-syntaxi hsymboli . . . ) (define-syntax unless
(syntax-rules ()
((unless test result1 result2 ...)
is equivalent to (if (not test)
((enum-set-constructor (hconstructor-syntaxi)) (begin result1 result2 ...)))))
(list ’hsymboli . . . )).
Example:
20.2. case-lambda
(define-enumeration color
(black white purple maroon)
This section describes the (r6rs case-lambda) library.
color-set)
Syntax: hTesti must be an expression. Semantics: A when • hFormalsi has the form
expression is evaluated by evaluating the htesti expres- (hvariable1 i . . . hvariablen i . hvariablen+1 )i
sion. If htesti evaluates to a true value, the remaining and the number of arguments is at least n.
20. Miscellaneous libraries 121
as follows
(force promise) procedure
(define-syntax delay
Promise must be a promise. (syntax-rules ()
Forces the value of promise (see delay, section 20.3). If no ((delay expression)
value has been computed for the promise, then a value is (make-promise (lambda () expression))))),
computed and returned. The value of the promise is cached where make-promise is defined as follows:
(or “memoized”) so that if it is forced a second time, the
previously computed value is returned. (define make-promise
(lambda (proc)
(force (delay (+ 1 2))) =⇒ 3 (let ((result-ready? #f)
(let ((p (delay (+ 1 2)))) (result #f))
(list (force p) (force p))) (lambda ()
=⇒ (3 3) (if result-ready?
result
122 Revised5.91 Scheme
• It may be the case that there is no means by which (eval expression environment-specifier ) procedure
a promise can be operationally distinguished from its
forced value. That is, expressions like the following Evaluates expression in the specified environment and
may evaluate to either #t or to #f, depending on the returns its value. Expression must be a valid
implementation: Scheme expression represented as a datum value, and
environment-specifier must be a library specifier, which can
(eqv? (delay 1) 1) =⇒ unspecified be created using the environment procedure described be-
(pair? (delay (cons 1 2))) =⇒ unspecified low.
If the first argument to eval is not a syntactically correct
• Some implementations may implement “implicit forc- expression, then eval must raise an exception with con-
ing,” where the value of a promise is forced by primi- dition type &syntax. Specifically, if the first argument to
tive procedures like cdr and +: eval is a definition, it must raise an exception with condi-
tion type &eval-definition.
(+ (delay (* 3 7)) 13) =⇒ 34
(environment import-spec . . . ) procedure
Import-spec must be a datum representing an
20.4. Command-line access himport speci (see section 6.1). The environment
procedure returns an environment corresponding to
The procedure described in this section is exported by the import-spec
(r6rs scripts) library. The bindings of the environment represented by the speci-
fier are immutable: If eval is applied to an expression that
(command-line-arguments) procedure attempts to assign to one of the variables of the environ-
ment, eval must raise an exception with a condition type
When a script is being executed, this returns a list of &contract.
strings with at least one element. The first element is an
implementation-specific name for the running script. The (library (foo)
following elements are command-line arguments according (export)
to the operating platform’s conventions. (import (r6rs))
(write (eval ’(let ((x 3)) x) (environment ’(r6rs)))
writes 3
21. Composite library
(library foo
The (r6rs) library is a composite of most of the libraries (export)
described in this report. The only exceptions are: (import (r6rs)
(write
• (r6rs records explicit) (section 13.2) (eval
’(eval:car (eval:cons 2 4))
• (r6rs mutable-pairs) (chapter 23) ’(add-prefix (only (r6rs) car cdr cons null?)
23. Mutable pairs 123
1. x is a pair, and n is 0; or
124 Revised5.91 Scheme
2. x is a pair p, n > 0, and there exists some time t1 in Note: The unspecified and non-terminating cases can occur
(t0 , tn ] such that taking the cdr of p at time t1 yields a only in implementations that allow the argument to be modi-
plausible list up to and including n − 1 between times fied by concurrent execution, which is beyond the scope of this
t1 and tn . document. To reduce the number of unspecified cases that must
be mentioned, the rest of this chapter will mostly ignore the
A plausible list of length n between times t0 and tn is a possibility of unspecified behavior being caused by concurrent
Scheme value x such that execution.
3. x is a pair p, n > 0, and there exist times t1 and t01 in (list-tail l k) procedure
(t0 , tn ] such that the car of x at time t01 is a pair and
L must be a plausible list up to k .
the cdr of x at time t1 is a plausible alist up to n − 1
between times t1 and tn .
(list-ref l k) procedure
A plausible alist of length n is defined similarly, as is a L must be a plausible list up to and including k .
plausible alist prefix of length n.
A plausible list (alist) between times t0 and tn is a plausible (map proc list1 list2 . . . ) procedure
list (alist) of some length n between those times. Proc must be a procedure; if any of the listj are nonempty,
then proc must take as many arguments as there are listj .
A natural number n must exist such that all listj are plau-
23.3. Procedures with list arguments sible lists of length n.
Note: In other words, an exception must be raised if no such
This section clarifies the domains of procedures in the base n exists. The existence of a natural number n such that all of
library and the (r6rs lists) library. the lists are plausible lists of length n is not by itself sufficient
to avoid the exception, however. If proc mutates the lists in
certain ways during the call to map, then an exception may
23.3.1. Base-library procedures still be raised, even in systems that do not allow concurrent
execution.
These are clarifications to the domains of the procedures of
the base library described in sections 9.12, 9.15, and 9.18: (let* ((ones (list 1))
(f (lambda (x)
(set-cdr! ones (list x))
(list? obj ) procedure (set! ones (cdr ones))
2)))
Returns #t if obj is a list that is not modified by set-cdr! ; ones is a plausible list
between entry and exit. Returns #f if obj is not a plausi- (map f ones)) =⇒ unspecified
ble list. Otherwise, this procedure returns an unspecified ; may not terminate
boolean or does not return at all.
24. R5 RS compatibility 125
(for-each proc list1 list2 . . . ) procedure (fold-left kons nil list1 list2 . . . listn ) procedure
A natural number n must exist such that all listj are plau- (fold-right kons nil list1 list2 . . . listn ) procedure
sible lists of length n. Kons must be a procedure; if the lists are non-empty, it
must take one more argument than there are lists. There
(list->string list) procedure must exist a natural number n such that every list is a plau-
List must be a plausible list where, for every natural num- sible list of length n between entry and some subsequent
ber n and for every plausible prefix xi of that argument of time before exit.
length n, there exists a time t with ti < t < tr , where tr is
the time of first return from list->string, for which the (remp proc list) procedure
car of xi is a character. (remove obj list) procedure
(remv obj list) procedure
(apply proc arg1 . . . args) procedure (remq obj list) procedure
Proc must be a procedure and args must be a plausible Proc must be a procedure; it must take a single argument
list. if list is non-empty. List must be a plausible list.
(modulo -13 4) =⇒ 3
(remainder -13 4) =⇒ -1
(modulo 13 -4) =⇒ -3
(remainder 13 -4) =⇒ 1
APPENDICES
Appendix A. Formal semantics (let ((tmp expr0))
(cond
This chapter is a placeholder for a formal semantics written
((memv tmp ’(key ...)) res1 res2 ...)
using PLT Redex [34, 35]. It will appear in the final version ...
of this report. (else else-res1 else-res2 ...))))
((case expr0
((keya ...) res1a res2a ...)
Appendix B. Sample definitions for de- ((keyb ...) res1b res2b ...)
rived forms ...)
This appendix contains sample definitions for some of the (let ((tmp expr0))
(cond
keywords described in this report in terms of simpler forms:
((memv tmp ’(keya ...)) res1a res2a ...)
((memv tmp ’(keyb ...)) res1b res2b ...)
cond ...)))))
The following script illustrates the use of [2] H. P. Barendregt. Introduction to the Lambda Cal-
integrate-system in integrating the system culus. Nieuw Archief voor Wisenkunde 4 (2):337–372,
1984.
dvC vC
C = −iL − [3] Alan Bawden and Jonathan Rees. Syntactic closures.
dt R
In Proceedings of the 1988 ACM Symposium on Lisp
diL and Functional Programming, pages 86–95.
L = vC
dt [4] Alan Bawden. Quasiquotation in Lisp. In Proceed-
which models a damped oscillator. ings of the ACM SIGPLAN Workshop on Partial
#! /usr/bin/env scheme-script Evaluation and Semantics-Based Program Manipu-
#!r6rs lation. Technical report BRICS-NS99 -1, University
(import (r6rs base) of Aarhus, pages 4–12, 1999.
(r6rs i/o simple)
(runge-kutta)) [5] Robert G. Burger and R. Kent Dybvig. Printing
floating-point numbers quickly and accurately. In
(define damped-oscillator Proceedings of the ACM SIGPLAN ’96 Conference
(lambda (R L C) on Programming Language Design and Implementa-
(lambda (state) tion, pages 108–116.
References 131
[7] William Clinger, editor. The revised revised report [19] Carol Fessenden, William Clinger, Daniel P. Fried-
on Scheme, or an uncommon Lisp. MIT Artificial man, and Christopher Haynes. Scheme 311 version 4
Intelligence Memo 848, August 1985. Also published reference manual. Indiana University Computer Sci-
as Computer Science Department Technical Report ence Technical Report 137, February 1983. Super-
174, Indiana University, June 1985. seded by [23].
[8] William Clinger. How to read floating point numbers [20] Matthew Flatt. PLT MzScheme: Language Manual,
accurately. In Proceedings of the ACM SIGPLAN No. 301. 2006. http://download.plt-scheme.org/
’90 Conference on Programming Language Design doc/301/html/mzscheme/
and Implementation, pages 92–101. Proceedings pub-
lished as SIGPLAN Notices 25(6), June 1990. [21] Matthew Flatt and Kent Dybvig SRFI 83: R6RS
Library Syntax. http://srfi.schemers.org/
[9] William Clinger and Jonathan Rees, editors. The srfi-83/, 2005.
revised4 report on the algorithmic language Scheme.
In ACM Lisp Pointers 4(3), pages 1–55, 1991. [22] Matthew Flatt and Mark Feeley. SRFI 75:
R6RS Unicode data. http://srfi.schemers.org/
[10] William Clinger and Jonathan Rees. Macros that srfi-75/, 2005.
work. In Proceedings of the 1991 ACM Conference
on Principles of Programming Languages, pages 155– [23] D. Friedman, C. Haynes, E. Kohlbecker, and
162. M. Wand. Scheme 84 interim reference manual. Indi-
ana University Computer Science Technical Report
[11] William Clinger. Proper Tail Recursion and Space
153, January 1985.
Efficiency. To appear in Proceedings of the 1998 ACM
Conference on Programming Language Design and [24] Martin Gasbichler and Michael Sperber
Implementation, June 1998. SRFI 22: Running Scheme Scripts on Unix.
[12] Will Clinger, R. Kent Dybvig, Michael Sperber http://srfi.schemers.org/srfi-22/, 2002.
and Anton van Straaten. SRFI 76: R6RS Records. [25] Lars T Hansen. SRFI 11: Syntax for receiving multi-
http://srfi.schemers.org/srfi-76/, 2005. ple values. http://srfi.schemers.org/srfi-11/,
[13] William D Clinger and Michael Sperber. SRFI 2000.
77: Preliminary Proposal for R6RS Arithmetic.
[26] IEEE Standard 754-1985. IEEE Standard for Binary
http://srfi.schemers.org/srfi-77/, 2005.
Floating-Point Arithmetic. IEEE, New York, 1985.
[14] R. Kent Dybvig, Robert Hieb, and Carl Bruggeman.
Syntactic abstraction in Scheme. Lisp and Symbolic [27] IEEE Standard 1178-1990. IEEE Standard for the
Computation 5(4):295–326, 1993. Scheme Programming Language. IEEE, New York,
1991.
[15] R. Kent Dybvig The Scheme Programming Lan-
guage. Third edition. MIT Press, Cambridge, 2003. [28] Richard Kelsey, William Clinger and Jonathan Rees,
http://www.scheme.com/tspl3/ editors. The revised5 report on the algorithmic lan-
guage Scheme. In Higher-Order and Symbolic Com-
[16] R. Kent Dybvig. Chez Scheme Version 7 putation 11(1), pages 7–105, 1998.
User’s Guide. Cadence Research Systems, 2005.
http://www.scheme.com/csug7/ [29] Richard Kelsey and Michael Sperber SRFI 34:
Exception Handling for Programs. http://srfi.
[17] R. Kent Dybvig SRFI 93: R6RS syntax-case schemers.org/srfi-34/, 2002.
macros. http://srfi.schemers.org/srfi-93/,
2006. [30] Richard Kelsey and Michael Sperber SRFI 35:
Conditions. http://srfi.schemers.org/srfi-35/,
[18] Sebastian Egner, Richard Kelsey, and Michael Sper- 2002.
ber. Cleaning up the tower: Numbers in Scheme. In
Proceedings of the Fifth ACM SIGPLAN Workshop [31] Eugene E. Kohlbecker Jr. Syntactic Extensions in
on Scheme and Functional Programming, pages 109– the Programming Language Lisp. PhD thesis, Indi-
120, September 22, 2004, Snowbird, Utah. Technical ana University, August 1986.
132 Revised5.91 Scheme
[32] Eugene E. Kohlbecker Jr., Daniel P. Friedman, [44] Guy Lewis Steele Jr. and Gerald Jay Sussman. The
Matthias Felleisen, and Bruce Duba. Hygienic macro revised report on Scheme, a dialect of Lisp. MIT Ar-
expansion. In Proceedings of the 1986 ACM Con- tificial Intelligence Memo 452, January 1978.
ference on Lisp and Functional Programming, pages
151–161. [45] Guy Lewis Steele Jr. Rabbit: a compiler for Scheme.
MIT Artificial Intelligence Laboratory Technical Re-
[33] Peter Landin. A correspondence between Algol 60 port 474, May 1978.
and Church’s lambda notation: Part I. Communica-
[46] Guy Lewis Steele Jr. Common Lisp: The Language,
tions of the ACM 8(2):89–101, February 1965.
second edition. Digital Press, Burlington MA, 1990.
[34] Jacob Matthews, Robert Bruce Findler, Matthew
[47] Gerald Jay Sussman and Guy Lewis Steele Jr.
Flatt, and Matthias Felleisen. A Visual Environ-
Scheme: an interpreter for extended lambda calcu-
ment for Developing Context-Sensitive Term Rewrit-
lus. MIT Artificial Intelligence Memo 349, December
ing Systems. In International Conference on Rewrit-
1975.
ing Techniques and Applications (RTA2004).
[48] Scheme Standardization charter. http://www.
[35] Jacob Matthews and Robert Bruce Findler. An schemers.org/Documents/Standards/Charter/
Operational Semantics for R5RS Scheme. In 2005 mar-2006.txt, March 2006.
Workshop on Scheme and Functional Programming.
September 2005. [49] Joseph E. Stoy. Denotational Semantics: The Scott-
Strachey Approach to Programming Language The-
[36] MIT Department of Electrical Engineering and Com- ory. MIT Press, Cambridge, 1977.
puter Science. Scheme manual, seventh edition.
September 1984. [50] Texas Instruments, Inc. TI Scheme Language Ref-
erence Manual. Preliminary version 1.0, November
[37] Peter Naur et al. Revised report on the algorith- 1985.
mic language Algol 60. Communications of the ACM
6(1):1–17, January 1963. [51] The Unicode Consortium. The Unicode Standard,
Version 5.0.0, defined by: The Unicode Standard,
[38] Paul Penfield, Jr. Principal values and branch cuts Version 5.0 (Boston, MA, Addison-Wesley, 2007.
in complex APL. In APL ’81 Conference Proceed- ISBN 0-321-48091-0).
ings, pages 248–256. ACM SIGAPL, San Fran-
cisco, September 1981. Proceedings published as [52] Oscar Waddell. Extending the Scope of Syntactic
APL Quote Quad 12(1), ACM, September 1981. Extension. PhD thesis, Indiana University, August
1999.
[39] Kent M. Pitman. The revised MacLisp manual (Sat-
urday evening edition). MIT Laboratory for Com- [53] William M. Waite and Gerhard Goos. Compiler Con-
puter Science Technical Report 295, May 1983. struction. Springer-Verlag, New York, 1984.
make-condition 75 octet 60
make-condition-type 75 odd? 39
make-enumeration 118 open-bytes-input-port 89
make-eq-hash-table 116 open-bytes-output-port 91
make-eqv-hash-table 116 open-bytes-reader 82
make-hash-table 116 open-bytes-writer 84
make-i/o-buffer 80 open-file-input-port 88
make-polar 42 open-file-input/output-port 92
make-record-constructor-descriptor 67 open-file-output-port 91
make-record-type-descriptor 66 open-file-reader 82
make-rectangular 42 open-file-reader+writer 84
make-simple-reader 80 open-file-writer 84
make-simple-writer 82 open-input-file 93
make-string 47 open-output-file 93
make-transcoder 87 open-reader-input-port 92
make-variable-transformer 109 open-string-input-port 89
make-vector 48 open-string-output-port 91
map 45; 124 open-writer-output-port 92
mark 108 operand 6
max 40 operator 6
member 65; 125 or 32
memp 65; 125 output ports 85
memq 65; 125 output-port-buffer-mode 91
memv 65; 125 output-port? 90
&message 76
message-condition? 76 pair 6; 44
meta level 23 pair? 44; 29
min 40 partition 64; 125
mod 40 pattern variable 54; 109
mod0 41 peek-char 93
modulo 126 phase 23
mutable 18 plausible list 123
nan? 39 port 85
native-endianness 60 port-eof? 88
native-eol-style 86 port-has-port-position? 88
negative? 39 port-has-set-port-position!? 88
newline 94 port-position 88
nil 43 port-transcoder 88
&no-infinities 102 port? 88
no-infinities? 102 position 87
&no-nans 102 positive? 39
no-nans? 102 predicate 35
&non-continuable 77 prefix notation 6
non-continuable? 77 procedure 6; 7
not 43 procedure call 24; 7
null-environment 126 procedure? 37; 29
null? 44; 29 promise 121
number 5; 9, 94 proper tail recursion 18
number->string 43 protocol 67
number? 38; 9, 29 put-bytes 92
numerator 41 put-char 92
numerical types 9 put-datum 92
put-string 92
#o 12; 14 put-string-n 92
object 5 put-u8 92
140 Revised5.91 Scheme
string 6; 47 transcoder-eol-style 87
string->list 47 transcoder-error-handling-mode 87
string->number 43 transformation procedure 109
string->symbol 46 transformer 25
string-append 47 true 29; 31, 43
string-ci-hash 118 truncate 41
string-ci<=? 59 type 29
string-ci<? 59
string-ci=? 59 u8-list->bytes 63
string-ci>=? 59 uint-list->bytes 63
string-ci>? 59 unbound 16; 24
string-copy 47 &undefined 77
string-downcase 59 undefined-violation? 77
string-fill! 47 unicode 46
string-foldcase 59 universe 118
string-hash 118 unless 120
string-length 47 unquote 53
string-normalize-nfc 59 unquote-splicing 53
string-normalize-nfd 59 unspecified 37
string-normalize-nfkc 59 unspecified behavior 20
string-normalize-nfkd 59 unspecified value 29; 37
string-ref 47 unspecified? 37; 29
string-set! 47 utf-16be-codec 86
string-titlecase 59 utf-16le-codec 86
string-upcase 59 utf-32be-codec 86
string<=? 47 utf-32le-codec 86
string<? 47 utf-8-codec 86
string=? 47
valid indexes 47; 48
string>=? 47
values 50
string>? 47
variable 6; 16, 13, 24
string? 47; 29
variable transformer 109
substitution 108
vector 6; 48
substring 47
vector->list 48
surrogate 46
vector-fill! 48
symbol 6; 13
vector-length 48
symbol->string 46; 18 vector-ref 48
symbol-hash 118 vector-set! 48
symbol? 46; 29 vector? 48; 29
syntactic abstraction 25 &violation 77
syntactic datum 10; 15, 8 violation? 77
syntactic keyword 16; 7, 13, 25 visiting 24
syntax 110; 77
syntax object 108; 109 &warning 76
syntax violation 20 warning? 76
syntax->datum 112 when 120
syntax-case 109 whitespace 12
syntax-rules 54 &who 78
syntax-violation 116 who-condition? 78
syntax-violation? 77 with-exception-handler 73
with-input-from-file 93
#t 13; 43 with-output-to-file 93
tail call 56 with-syntax 114
tan 42 wrap 108
transcoder 86 wrapped syntax object 108
transcoder-codec 87 write 94
142 Revised5.91 Scheme
write-char 94
writer-bytes 84
writer-chunk-size 83
writer-close 84
writer-descriptor 83
writer-end-position 84
writer-get-position 83
writer-has-end-position? 84
writer-has-get-position? 83
writer-has-set-position!? 84
writer-id 83
writer-set-position! 84
writer-write! 83
writer? 82
#x 12; 14
zero? 39