Revised7 Report on the Algorithmic Language Scheme

ALEX SHINN,JOHN COWAN, AND ARTHUR A. GLECKLER (Editors)

STEVEN GANZ ALEXEY RADUL OLIN SHIVERS AARON W. HSU JEFFREY . READ ALARIC SNELL-PYM BRADLEY LUCIER DAVID RUSH GERALD J. SUSSMAN EMMANUEL MEDERNACH BENJAMIN L. RUSSEL

RICHARD KELSEY,WILLIAM CLINGER, AND JONATHAN REES (Editors, Revised5 Report on the Algorithmic Language Scheme)

MICHAEL SPERBER, R. KENT DYBVIG,, AND ANTON VAN STRAATEN (Editors, Revised6 Report on the Algorithmic Language Scheme)

Dedicated to the memory of John McCarthy and *** DRAFT *** December 9, 2012 2 Revised7 Scheme

SUMMARY CONTENTS The report gives a defining description of the programming Introduction ...... 3 language Scheme. Scheme is a statically scoped and prop- 1 Overview of Scheme ...... 5 erly tail recursive dialect of the Lisp 1.1 Semantics ...... 5 invented by Guy Lewis Steele Jr. and . 1.2 Syntax ...... 5 1.3 Notation and terminology ...... 5 It was designed to have exceptionally clear and simple se- 2 Lexical conventions ...... 7 mantics and few different ways to form expressions. A wide 2.1 Identifiers ...... 7 variety of programming paradigms, including imperative, 2.2 Whitespace and comments ...... 8 functional, and object-oriented styles, find convenient ex- 2.3 Other notations ...... 8 pression in Scheme. 2.4 Datum labels ...... 9 The introduction offers a brief history of the language and 3 Basic concepts ...... 9 3.1 Variables, syntactic keywords, and regions ...... 9 of the report. 3.2 Disjointness of types ...... 10 The first three chapters present the fundamental ideas of 3.3 External representations ...... 10 the language and describe the notational conventions used 3.4 Storage model ...... 10 for describing the language and for writing programs in the 3.5 Proper tail recursion ...... 11 language. 4 Expressions ...... 12 4.1 Primitive expression types ...... 12 Chapters 4 and 5 describe the syntax and semantics of 4.2 Derived expression types ...... 14 expressions, definitions, programs, and libraries. 4.3 Macros ...... 21 5 Program structure ...... 25 Chapter 6 describes Scheme’s built-in procedures, which 5.1 Programs ...... 25 include all of the language’s data manipulation and in- 5.2 Import declarations ...... 25 put/output primitives. 5.3 Variable definitions ...... 25 Chapter 7 provides a formal syntax for Scheme written in 5.4 Syntax definitions ...... 26 extended BNF, along with a formal denotational semantics. 5.5 Record-type definitions ...... 27 An example of the use of the language follows the formal 5.6 Libraries ...... 28 5.7 The REPL ...... 29 syntax and semantics. 6 Standard procedures ...... 30 Appendix A provides a list of the standard libraries and 6.1 Equivalence predicates ...... 30 the identifiers that they export. 6.2 Numbers ...... 32 6.3 Booleans ...... 40 Appendix B provides a list of optional but standardized 6.4 Pairs and lists ...... 40 implementation feature names. 6.5 Symbols ...... 43 The report concludes with a list of references and an al- 6.6 Characters ...... 44 phabetic index. 6.7 Strings ...... 45 6.8 Vectors ...... 47 6.9 Bytevectors ...... 49 6.10 Control features ...... 50 6.11 Exceptions ...... 53 6.12 Environments and evaluation ...... 54 6.13 Input and output ...... 55 6.14 System interface ...... 59 7 Formal syntax and semantics ...... 61 7.1 Formal syntax ...... 61 7.2 Formal semantics ...... 64 7.3 Derived expression types ...... 68 A Standard Libraries ...... 73 B Standard Feature Identifiers ...... 76 Language changes ...... 77 Additional material ...... 80 Example ...... 81 References ...... 82 Alphabetic index of definitions of concepts, keywords, and procedures ...... 84 Introduction 3 INTRODUCTION

Programming languages should be designed not by piling Programming Language in 1991 [20]. In 1998, several ad- feature on top of feature, but by removing the weaknesses ditions to the IEEE standard, including high-level hygienic and restrictions that make additional features appear nec- macros, multiple return values, and eval, were finalized as essary. Scheme demonstrates that a very small number of the R5RS [2]. rules for forming expressions, with no restrictions on how In the fall of 2006, work began on a more ambitious stan- they are composed, suffice to form a practical and efficient dard, including many new improvements and stricter re- programming language that is flexible enough to support quirements made in the interest of improved portability. most of the major programming paradigms in use today. The resulting standard, the R6RS, was completed in Au- Scheme was one of the first programming languages to in- gust 2007 [1], and was organized as a core language and set corporate first-class procedures as in the lambda calculus, of mandatory standard libraries. Several new implementa- thereby proving the usefulness of static scope rules and tions of Scheme conforming to it were created. However, block structure in a dynamically typed language. Scheme most existing R5RS implementations (even excluding those was the first major dialect of Lisp to distinguish procedures which are essentially unmaintained) did not adopt R6RS, from lambda expressions and symbols, to use a single lex- or adopted only selected parts of it. ical environment for all variables, and to evaluate the op- In consequence, the Scheme Steering Committee decided in erator position of a procedure call in the same way as an August 2009 to divide the standard into two separate but operand position. By relying entirely on procedure calls compatible languages — a “small” language, suitable for to express iteration, Scheme emphasized the fact that tail- educators, researchers, and users of embedded languages, recursive procedure calls are essentially GOTOs that pass focused on R5RS compatibility, and a “large” language fo- arguments, thus allowing a programming style that is both cused on the practical needs of mainstream software de- coherent and efficient. Scheme was the first widely used velopment, intended to become a replacement for R6RS. programming language to embrace first-class escape proce- The present report describes the “small” language of that dures, from which all previously known sequential control effort: therefore it cannot be considered in isolation as the structures can be synthesized. A subsequent version of successor to R6RS. Scheme introduced the concept of exact and inexact num- bers, an extension of ’s generic arithmetic. We intend this report to belong to the entire Scheme com- More recently, Scheme became the first programming lan- munity, and so we grant permission to copy it in whole or in guage to support hygienic macros, which permit the syntax part without fee. In particular, we encourage implementers of a block-structured language to be extended in a consis- of Scheme to use this report as a starting point for manuals tent and reliable manner. and other documentation, modifying it as necessary.

Background Acknowledgments The first description of Scheme was written in 1975 [36]. A We would like to thank the members of the Steering revised report [33] appeared in 1978, which described the Committee, William Clinger, Marc Feeley, Chris Hanson, evolution of the language as its MIT implementation was Jonathan Rees, and Olin Shivers, for their support and upgraded to support an innovative [34]. Three guidance. distinct projects began in 1981 and 1982 to use variants of Scheme for courses at MIT, Yale, and Indiana Univer- This report is very much a community effort, and we’d like sity [29, 25, 16]. An introductory text- to thank everyone who provided comments and feedback, book using Scheme was published in 1984 [3]. including the following people: Eli Barzilay, Peter Bex, Per Bothner, Taylor Campbell, Ray Dillinger, Brian Har- As Scheme became more widespread, local dialects be- vey, Aubrey Jaffer, Shiro Kawai, Oleg Kiselyov, Jonathan gan to diverge until students and researchers occasion- Kraut, Thomas Lord, Vitaly Magerya, Vincent Manis, ally found it difficult to understand code written at other Daichi Oohashi, Jeronimo Pellegrini, Jussi Piitulainen, sites. Fifteen representatives of the major implementations Alex Queiroz, Jim Rees, Grant Rettke, Jay Reynolds Free- of Scheme therefore met in October 1984 to work toward man, Andrew Robbins, Arthur Smyles, Malcolm Tredin- a better and more widely accepted standard for Scheme. nick, Andre van Tonder, Daniel Villeneuve, Denis Wash- Their report, the RRRS [8], was published at MIT and In- ington, Alan Watson, Mark Weaver, and Andy Wingo. diana University in the summer of 1985. Further revision took place in the spring of 1986, resulting in the R3RS [31]. In addition we would like to thank all the past editors, and Work in the spring of 1988 resulted in R4RS [10], which the people who helped them in turn: , Nor- became the basis for the IEEE Standard for the Scheme man Adams, David Bartley, Alan Bawden, Michael Blair, 4 Revised7 Scheme

Gary Brooks, George Carrette, Andy Cromarty, Pavel Cur- tis, Jeff Dalton, Olivier Danvy, Ken Dickey, Bruce Duba, Robert Findler, Andy Freeman, Richard Gabriel, Yekta G¨ursel,Ken Haase, Robert Halstead, Robert Hieb, Paul Hudak, Morry Katz, Eugene Kohlbecker, Chris Lindblad, Jacob Matthews, Mark Meyer, Jim Miller, Don Oxley, Jim Philbin, , John Ramsdell, Guillermo Rozas, Mike Shaff, Jonathan Shapiro, Guy Steele, Julie Sussman, Perry Wagle, Mitchel Wand, Daniel Weise, Henry Wu, and Ozan Yigit. We thank Carol Fessenden, Daniel Friedman, and Christopher Haynes for permission to use text from the Scheme 311 version 4 reference manual. We thank Texas Instruments, Inc. for permission to use text from the TI Scheme Language Reference Manual [38]. We gladly ac- knowledge the influence of manuals for MIT Scheme [25], T [30], Scheme 84 [17], Common Lisp [35], and Algol 60 [26], as well as the following SRFIs: 0, 1, 4, 6, 9, 11, 13, 16, 30, 34, 39, 43, 46, 62, 87. 1. Overview of Scheme 5 DESCRIPTION OF THE LANGUAGE

1. Overview of Scheme its place is a distinction between exact arithmetic, which corresponds to the mathematical ideal, and inexact arith- 1.1. Semantics metic on approximations. Exact arithmetic is not limited to integers. This section gives an overview of Scheme’s semantics. A detailed informal semantics is the subject of chapters 3 through 6. For reference purposes, section 7.2 provides a 1.2. Syntax formal semantics of Scheme. Scheme is a statically scoped programming language. Each Scheme, like most dialects of Lisp, employs a fully paren- use of a variable is associated with a lexically apparent thesized prefix notation for programs and other data; the binding of that variable. grammar of Scheme generates a sublanguage of the lan- guage used for data. An important consequence of this Scheme is a dynamically typed language. Types are asso- simple, uniform representation is that Scheme programs ciated with values (also called objects) rather than with and data can easily be treated uniformly by other Scheme variables. Statically typed languages, by contrast, asso- programs. For example, the eval procedure evaluates a ciate types with variables and expressions as well as with Scheme program expressed as data. values. The read procedure performs syntactic as well as lexical All objects created in the course of a Scheme computation, decomposition of the data it reads. The read procedure including procedures and continuations, have unlimited ex- parses its input as data (section 7.1.2), not as program. tent. No Scheme object is ever destroyed. The reason that The formal syntax of Scheme is described in section 7.1. implementations of Scheme do not (usually!) run out of storage is that they are permitted to reclaim the storage occupied by an object if they can prove that the object 1.3. Notation and terminology cannot possibly matter to any future computation. Implementations of Scheme are required to be properly 1.3.1. Base and optional features tail-recursive. This allows the execution of an iterative Every identifier defined in this report appears in one or computation in constant space, even if the iterative compu- more of several libraries. Identifiers defined in the base li- tation is described by a syntactically recursive procedure. brary are not marked specially in the body of the report. Thus with a properly tail-recursive implementation, iter- This library includes the core syntax of Scheme and gener- ation can be expressed using the ordinary procedure-call ally useful procedures that manipulate data. For example, mechanics, so that special iteration constructs are useful the variable abs is bound to a procedure of one argument only as syntactic sugar. See section 3.5. that computes the absolute value of a number, and the Scheme procedures are objects in their own right. Proce- variable + is bound to a procedure that computes sums. dures can be created dynamically, stored in data structures, The full list all the standard libraries and the identifiers returned as results of procedures, and so on. they export is given in Appendix A. One distinguishing feature of Scheme is that continuations, All implementations of Scheme: which in most other languages only operate behind the • Must provide the base library and all the identifiers scenes, also have “first-class” status. Continuations are exported from it. useful for implementing a wide variety of advanced control constructs, including non-local exits, backtracking, and • May provide or omit the other libraries given in this coroutines. See section 6.10. report, but each library must either be provided in Arguments to Scheme procedures are always passed by its entirety, exporting no additional identifiers, or else value, which means that the actual argument expressions omitted altogether. are evaluated before the procedure gains control, regardless • May provide other libraries not described in this re- of whether the procedure needs the result of the evaluation. port. Scheme’s model of arithmetic is designed to remain as in- • May also extend the function of any identifier in this dependent as possible of the particular ways in which num- report, provided the extensions are not in conflict with bers are represented within a computer. In Scheme, every the language reported here. integer is a rational number, every rational is a real, and every real is a complex number. Thus the distinction be- • Must support portable code by providing a mode of tween integer and real arithmetic, so important to many operation in which the lexical syntax does not conflict programming languages, does not appear in Scheme. In with the lexical syntax described in this report. 6 Revised7 Scheme

1.3.2. Error situations and unspecified behavior capitalized in this report, are to be interpreted as described in RFC 2119 [6]. In particular, “must” and “must not” are When speaking of an error situation, this report uses the used only when absolute restrictions are placed on imple- phrase “an error is signaled” to indicate that implementa- mentations. tions must detect and report the error. An error is signaled by raising a non-continuable exception, as if by the proce- dure raise as described in section 6.11. The object raised 1.3.3. Entry format is implementation-dependent and need not be distinct from objects previously used for the same purpose. In addition Chapters 4 and 6 are organized into entries. Each entry to errors signaled in situations described in this report, pro- describes one language feature or a group of related fea- grammers can signal their own errors and handle signaled tures, where a feature is either a syntactic construct or a errors. procedure. An entry begins with one or more header lines of the form The phrase “an error that satisfies predicate is signaled” means that an error is signaled as above. Furthermore, if template category the object that is signaled is passed to the specified predi- for identifiers in the base library, or cate (such as file-error? or read-error?), the predicate returns #t. template library category If such wording does not appear in the discussion of an er- where library is the short name of a library as defined in ror, then implementations are not required to detect or Appendix A. report the error, though they are encouraged to do so. If category is “syntax,” the entry describes an expression Such a situation is sometimes, but not always, referred type, and the template gives the syntax of the expression to with the phrase “an error.” In such a situation, an im- type. Components of expressions are designated by syn- plementation may or may not signal an error; if it does tactic variables, which are written using angle brackets, signal an error, the object that is signaled may or may for example hexpressioni and hvariablei. Syntactic vari- not satisfy the predicates error-object?, file-error?, ables are intended to denote segments of program text; for or read-error?. Alternatively, implementations may pro- example, hexpressioni stands for any string of characters vide non-portable extensions. which is a syntactically valid expression. The notation For example, it is an error for a procedure to be passed an argument of a type that the procedure is not explicitly hthing1i ... specified to handle, even though such domain errors are indicates zero or more occurrences of a hthingi, and seldom mentioned in this report. Implementations may hthing i hthing i ... signal an error, extend a procedure’s domain of definition 1 2 to include such arguments, or fail catastrophically. indicates one or more occurrences of a hthingi. This report uses the phrase “may report a violation of an If category is “auxiliary syntax,” then the entry describes implementation restriction” to indicate circumstances un- a syntax binding that occurs only as part of specific sur- der which an implementation is permitted to report that rounding expressions. Any use as an independent syntactic it is unable to continue execution of a correct program construct or variable is an error. because of some restriction imposed by the implementa- tion. Implementation restrictions are discouraged, but im- If category is “procedure,” then the entry describes a pro- plementations are encouraged to report violations of im- cedure, and the header line gives a template for a call to the plementation restrictions. procedure. Argument names in the template are italicized. Thus the header line For example, an implementation may report a violation of an implementation restriction if it does not have enough (vector-ref vector k) procedure storage to run a program, or if an arithmetic operation indicates that the procedure bound to the vector-ref would produce an exact number that is too large for the variable takes two arguments, a vector vector and an exact implementation to represent. non-negative integer k (see below). The header lines If the value of an expression is said to be “unspecified,” (make-vector k) procedure then the expression must evaluate to some object without (make-vector k fill) procedure signaling an error, but the value depends on the imple- mentation; this report explicitly does not say what value indicate that the make-vector procedure must be defined is returned. to take either one or two arguments. Finally, the words and phrases “must,” “must not,” It is an error for an procedure to be presented with an ar- “shall,” “shall not,” “should,” “should not,” “may,” “re- gument that it is not specified to handle. For succinctness, quired,” “recommended,” and “optional,” although not we follow the convention that if an argument name is also 2. Lexical conventions 7 the name of a type listed in section 3.2, then it is an error if means that the expression (* 5 8) evaluates to the ob- that argument is not of the named type. For example, the ject 40. Or, more precisely: the expression given by the header line for vector-ref given above dictates that the sequence of characters “(* 5 8)” evaluates, in the initial first argument to vector-ref is a vector. The following environment, to an object that can be represented exter- naming conventions also imply type restrictions: nally by the sequence of characters “40.” See section 3.3 for a discussion of external representations of objects. alist association list (list of pairs) boolean boolean value (#t or #f) byte exact integer 0 ≤ byte < 256 1.3.5. Naming conventions bytevector bytevector By convention, ? is the final character of the names of char character procedures that always return a boolean value. Such pro- end exact non-negative integer cedures are called predicates. k, k1, . . . kj, ... exact non-negative integer letter alphabetic character Similarly, ! is the final character of the names of proce- list, list1, . . . listj, ... list (see section 6.4) dures that store values into previously allocated locations n, n1, . . . nj, ... integer (see section 3.4). Such procedures are called mutation pro- obj any object cedures. The value returned by a mutation procedure is pair pair unspecified. port port By convention, “->” appears within the names of proce- proc procedure dures that take an object of one type and return an anal- q, q , . . . q , ... rational number 1 j ogous object of another type. For example, list->vector start exact non-negative integer takes a list and returns a vector whose elements are the string string same as those of the list. symbol symbol thunk zero-argument procedure vector vector 2. Lexical conventions x, x , . . . x , ... real number 1 j This section gives an informal account of some of the lexical y, y , . . . y , ... real number 1 j conventions used in writing Scheme programs. For a formal z, z , . . . z , ... complex number 1 j syntax of Scheme, see section 7.1.

The names start and end are used as indexes into strings, vectors, and bytevectors. Their use implies the following: 2.1. Identifiers

• It is an error if start is greater than end. An identifier is any sequence of letters, digits, and “ex- tended identifier characters” provided that it does not have • It is an error if end is greater than the length of the a prefix which is a valid number. However, the . token (a string, vector, or bytevector. single period) used in the list syntax is not an identifier. All implementations of Scheme must support the following • If start is omitted, it is assumed to be zero. extended identifier characters:

• If end is omitted, it assumed to be the length of the !$%&*+-./:<=>?@^_~ string, vector, or bytevector. Alternatively, an identifier can be represented by a se- • The index start is always inclusive and the index end quence of zero or more characters enclosed within verti- is always exclusive. As an example, consider a string. cal lines (|), analogous to string literals. Any character, If start and end are the same, an empty substring is including whitespace characters, but excluding the back- referred to, and if start is zero and end is the length slash and vertical line characters, may appear verbatim in of string, then the entire string is referred to. such an identifier. In addition, characters may be speci- fied using an hinline hex escapei. For example, the iden- tifier |H\x65;llo| is the same identifier as Hello, and in 1.3.4. Evaluation examples an implementation that supports the appropriate Unicode character the identifier |\x3BB;| is the same as the iden- The symbol “=⇒” used in program examples is read “eval- tifier λ. uates to.” For example, It is also possible to include the backslash and vertical line (* 5 8) =⇒ 40 characters, as well as any other character, in an identifier 8 Revised7 Scheme written with vertical lines. This is done with the same used for improved readability and as necessary to separate escapes available in strings. For example, |\t\t| and tokens from each other, a token being an indivisible lexi- |\x9;\x9;| are the same. Note that || is a valid iden- cal unit such as an identifier or number, but is otherwise tifier that is different from any other identifier. insignificant. Whitespace can occur between any two to- Here are some examples of identifiers: kens, but not within a token. Whitespace occurring inside a string or inside a symbol delimited by vertical lines is ... + significant. +soup+ <=? ->string a34kTMNs The lexical syntax includes several comment forms. Com- lambda list->vector ments are treated exactly like whitespace. q V17a A semicolon (;) indicates the start of a line comment. The |two words| |two\x20;words| comment continues to the end of the line on which the the-word-recursion-has-many-meanings semicolon appears. See section 7.1.1 for the formal syntax of identifiers. Another way to indicate a comment is to prefix a hdatumi Identifiers have two uses within Scheme programs: (cf. section 7.1.2) with #; and optional hwhitespacei. The comment consists of the comment prefix #;, the space, and • Any identifier can be used as a variable or as a syn- the hdatumi together. This notation is useful for “com- tactic keyword (see sections 3.1 and 4.3). menting out” sections of code. • When an identifier appears as a literal or within a Block comments are indicated with properly nested #| and literal (see section 4.1.2), it is being used to denote a |# pairs. symbol (see section 6.5). #| The FACT procedure computes the factorial In contrast with earlier revisions of the report [2], the syn- of a non-negative integer. tax distinguishes between upper and lower case in identi- |# fiers and in characters specified using their names. How- (define fact ever, it does not distinguish between upper and lower case (lambda (n) in numbers, nor in hinline hex escapesi used in the syntax (if (= n 0) of identifiers, characters, or strings. None of the identi- #;(= n 1) fiers defined in this report contain upper-case characters, 1 ;Base case: return 1 even when they appear to do so as a result of the English- (* n (fact (- n 1)))))) language convention of capitalizing the first word of a sen- tence. The following directives give explicit control over case fold- 2.3. Other notations ing. For a description of the notations used for numbers, see section 6.2. #!fold-case #!no-fold-case . + - These are used in numbers, and may also occur any- These directives may appear anywhere comments are per- where in an identifier. A delimited plus or minus sign mitted (see section 2.2) but must be followed by a de- by itself is also an identifier. A delimited period (not limiter. They are treated as comments, except that occurring within a number or identifier) is used in the they affect the reading of subsequent data from the same notation for pairs (section 6.4), and to indicate a rest- port. The #!fold-case directive causes subsequent iden- parameter in a formal parameter list (section 4.1.4). tifiers and character names to be case-folded as if by Note that a sequence of two or more periods is an string-foldcase (see section 6.7). It has no effect on identifier. character literals. The #!no-fold-case directive causes a return to the default, non-folding behavior. () Parentheses are used for grouping and to notate lists (section 6.4).

2.2. Whitespace and comments ’ The apostrophe (single quote) character is used to indi- cate literal data (section 4.1.2). Whitespace characters include the space, tab, and new- line characters. (Implementations may provide additional ` The grave accent (backquote) character is used to indi- whitespace characters such as page break.) Whitespace is cate partly constant data (section 4.2.8). 3. Basic concepts 9

, ,@ The character comma and the sequence comma at- addition, it is an error if the reference appears as the la- sign are used in conjunction with quasiquotation (sec- belled object itself (as in #hni= #hni#), because the object tion 4.2.8). labelled by #hni= is not well defined in this case.

" The quotation mark character is used to delimit strings It is an error for a hprogrami or hlibraryi to include circular (section 6.7). references except in literals. In particular, it is an error for quasiquote (section 4.2.8) to contain them. \ Backslash is used in the syntax for character constants (section 6.6) and as an escape character within string #1=(begin (display #\x) #1#) =⇒ error constants (section 6.7) and identifiers (section 7.1.1).

[]{} Left and right square and curly brackets (braces) are reserved for possible future extensions to the lan- 3. Basic concepts guage. 3.1. Variables, syntactic keywords, and re- # The number sign is used for a variety of purposes de- gions pending on the character that immediately follows it: An identifier can name either a type of syntax or a location #t #f These are the boolean constants (section 6.3), along where a value can be stored. An identifier that names a with the alternatives #true and #false. type of syntax is called a syntactic keyword and is said to be bound to a transformer for that syntax. An identifier that #\ This introduces a character constant (section 6.6). names a location is called a variable and is said to be bound #( This introduces a vector constant (section 6.8). Vector to that location. The set of all visible bindings in effect at constants are terminated by ) . some point in a program is known as the environment in effect at that point. The value stored in the location to #u8( This introduces a bytevector constant (section 6.9). which a variable is bound is called the variable’s value. Bytevector constants are terminated by ) . By abuse of terminology, the variable is sometimes said to name the value or to be bound to the value. This is These are used in the notation for #e #i #b #o #d #x not quite accurate, but confusion rarely results from this numbers (section 6.2.5). practice. #hni= #hni# These are used for labeling and referencing Certain expression types are used to create new kinds of other literal data (section 2.4). syntax and to bind syntactic keywords to those new syn- taxes, while other expression types create new locations and bind variables to those locations. These expression 2.4. Datum labels types are called binding constructs. Those that bind syn- tactic keywords are listed in section 4.3. The most fun- #hni=hdatumi lexical syntax damental of the variable binding constructs is the lambda #hni# lexical syntax expression, because all other variable binding constructs can be explained in terms of lambda expressions. The The lexical syntax #hni=hdatumi reads the same as other variable binding constructs are let, let*, letrec, hdatumi, but also results in hdatumi being labelled by hni. letrec*, let-values, let*-values, and do expressions It is an error if hni is not a sequence of digits. (see sections 4.1.4, 4.2.2, and 4.2.4). The lexical syntax #hni# serves as a reference to some ob- Scheme is a language with block structure. To each place ject labelled by #hni=; the result is the same object as the where an identifier is bound in a program there corresponds #hni= (see section 6.1). a region of the program text within which the binding is Together, these syntaxes permit the notation of structures visible. The region is determined by the particular bind- with shared or circular substructure. ing construct that establishes the binding; if the binding is established by a lambda expression, for example, then its (let ((x (list ’a ’b ’c))) region is the entire lambda expression. Every mention of (set-cdr! (cddr x) x) an identifier refers to the binding of the identifier that es- x) =⇒ #0=(a b c . #0#) tablished the innermost of the regions containing the use. If there is no binding of the identifier whose region con- The scope of a datum label is the portion of the outermost tains the use, then the use refers to the binding for the datum in which it appears that is to the right of the label. variable in the global environment, if any (chapters 4 and Consequently, a reference #hni# may occur only after a la- 6); if there is no binding for the identifier, it is said to be bel #hni=; it is an error to attempt a forward reference. In unbound. 10 Revised7 Scheme

3.2. Disjointness of types which are the symbol + and the integers 2 and 6. Scheme’s syntax has the property that any sequence of characters No object satisfies more than one of the following predi- that is an expression is also the external representation of cates: some object. This can lead to confusion, since it is not always obvious out of context whether a given sequence of boolean? bytevector? characters is intended to denote data or program, but it is char? eof-object? also a source of power, since it facilitates writing programs null? number? pair? port? such as interpreters and that treat programs as procedure? string? data (or vice versa). symbol? vector? The syntax of external representations of various kinds of objects accompanies the description of the primitives for and all predicates created by define-record-type. manipulating the objects in the appropriate sections of chapter 6. These predicates define the types boolean, pair, symbol, number, char (or character), string, vector, bytevector, port, procedure, eof-object, the empty list object, and all record 3.4. Storage model types. Although there is a separate boolean type, any Scheme Variables and objects such as pairs, strings, vectors, and value can be used as a boolean value for the purpose of bytevectors implicitly denote locations or sequences of lo- a conditional test. As explained in section 6.3, all values cations. A string, for example, denotes as many locations count as true in such a test except for #f. This report uses as there are characters in the string. A new value can be the word “true” to refer to any Scheme value except #f, stored into one of these locations using the string-set! and the word “false” to refer to #f. procedure, but the string continues to denote the same lo- cations as before. 3.3. External representations An object fetched from a location, by a variable reference or by a procedure such as car, vector-ref, or string-ref, is operationally equivalent to the object last stored in the An important concept in Scheme (and Lisp) is that of the location before the fetch. external representation of an object as a sequence of char- acters. For example, an external representation of the inte- Every location is marked to show whether it is in use. No ger 28 is the sequence of characters “28”, and an external variable or object ever refers to a location that is not in use. representation of a list consisting of the integers 8 and 13 Whenever this report speaks of storage being allocated for is the sequence of characters “(8 13)”. a variable or object, what is meant is that an appropriate number of locations are chosen from the set of locations The external representation of an object is not neces- that are not in use, and the chosen locations are marked sarily unique. The integer 28 also has representations to indicate that they are now in use before the variable or “#e28.000” and “#x1c”, and the list in the previous para- object is made to denote them. graph also has the representations “( 08 13 )” and “(8 . (13 . ()))” (see section 6.4). Every object that denotes locations is either mutable or immutable. Literal constants, the strings returned by Many objects have standard external representations, but symbol->string, and possibly the environment returned some, such as procedures, do not have standard represen- by scheme-report-environment are immutable objects. tations (although particular implementations may define All objects created by the other procedures listed in this representations for them). report are mutable. It is an error to attempt to store a An external representation can be written in a program to new value into a location that is denoted by an immutable obtain the corresponding object (see quote, section 4.1.2). object. External representations can also be used for input and These locations are to be understood as conceptual, not output. The procedure read (section 6.13.2) parses ex- physical. Hence, they do not necessarily correspond to ternal representations, and the procedure write (sec- memory addresses, and even if they do, the memory ad- tion 6.13.3) generates them. Together, they provide an dress might not be constant. elegant and powerful input/output facility. Rationale: In many systems it is desirable for constants (i.e. Note that the sequence of characters “(+ 2 6)” is not an the values of literal expressions) to reside in read-only memory. external representation of the integer 8, even though it is an Making it an error to alter constants permits this implementa- expression evaluating to the integer 8; rather, it is an exter- tion strategy, while not requiring other systems to distinguish nal representation of a three-element list, the elements of between mutable and immutable objects. 3. Basic concepts 11

3.5. Proper tail recursion (if hexpressioni htail expressioni htail expressioni) (if hexpressioni htail expressioni) Implementations of Scheme are required to be properly tail- recursive. Procedure calls that occur in certain syntactic (cond hcond clausei+) contexts defined below are tail calls. A Scheme imple- (cond hcond clausei* (else htail sequencei)) mentation is properly tail-recursive if it supports an un- bounded number of active tail calls. A call is active if (case hexpressioni the called procedure might still return. Note that this in- hcase clausei+) cludes calls that might be returned from either by the cur- (case hexpressioni rent continuation or by continuations captured earlier by hcase clausei* call-with-current-continuation that are later invoked. (else htail sequencei)) In the absence of captured continuations, calls could return at most once and the active calls would be those that had (and hexpressioni* htail expressioni) not yet returned. A formal definition of proper tail recur- (or hexpressioni* htail expressioni) sion can be found in [12]. Rationale: (when htesti htail sequencei) (unless htesti htail sequencei) Intuitively, no space is needed for an active tail call because the continuation that is used in the tail call has the same semantics as the continuation passed to the procedure containing the call. (let (hbinding speci*) htail bodyi) Although an improper implementation might use a new con- (let hvariablei (hbinding speci*) htail bodyi) tinuation in the call, a return to this new continuation would (let* (hbinding speci*) htail bodyi) be followed immediately by a return to the continuation passed (letrec (hbinding speci*) htail bodyi) to the procedure. A properly tail-recursive implementation re- (letrec* (hbinding speci*) htail bodyi) turns to that continuation directly. (let-values (hformalsi*) htail bodyi) Proper tail recursion was one of the central ideas in Steele and (let*-values (hformalsi*) htail bodyi) Sussman’s original version of Scheme. Their first Scheme in- terpreter implemented both functions and actors. Control flow (let-syntax (hsyntax speci*) htail bodyi) was expressed using actors, which differed from functions in (letrec-syntax (hsyntax speci*) htail bodyi) that they passed their results on to another actor instead of returning to a caller. In the terminology of this section, each (begin htail sequencei) actor finished with a tail call to another actor. Steele and Sussman later observed that in their interpreter the (do (hiteration speci*) code for dealing with actors was identical to that for functions (htesti htail sequencei) and thus there was no need to include both in the language. hexpressioni*) A tail call is a procedure call that occurs in a tail con- text. Tail contexts are defined inductively. Note that a tail where context is always determined with respect to a particular lambda expression. hcond clausei −→ (htesti htail sequencei) hcase clausei −→ ((hdatumi*) htail sequencei) • The last expression within the body of a lambda ex- pression, shown as htail expressioni below, occurs in htail bodyi −→ hdefinitioni* htail sequencei a tail context. The same is true of all the bodies of htail sequencei −→ hexpressioni* htail expressioni case-lambda expressions.

(lambda hformalsi • If a cond or case expression is in a tail con- hdefinitioni* hexpressioni* htail expressioni) text, and has a clause of the form (hexpression1i => hexpression2i) then the (implied) call to the proce- • If one of the following expressions is in a tail context, dure that results from the evaluation of hexpression2i then the subexpressions shown as htail expressioni are is in a tail context. hexpression2i itself is not in a tail in a tail context. These were derived from rules in the context. grammar given in chapter 7 by replacing some occur- rences of hbodyi with htail bodyi, some occurrences of Certain procedures defined in this report are also re- hexpressioni with htail expressioni, and some occur- quired to perform tail calls. The first argument passed rences of hsequencei with htail sequencei. Only those to apply and to call-with-current-continuation, and rules that contain tail contexts are shown here. the second argument passed to call-with-values, must 12 Revised7 Scheme be called via a tail call. Similarly, eval must evaluate its tion 3.3). This notation is used to include literal constants first argument as if it were in tail position within the eval in Scheme code. procedure. (quote a) =⇒ a In the following example the only tail call is the call to f. (quote #(a b c)) =⇒ #(a b c) None of the calls to g or h are tail calls. The reference to (quote (+ 1 2)) =⇒ (+ 1 2) x is in a tail context, but it is not a call and thus is not a tail call. (quote hdatumi) can be abbreviated as ’hdatumi. The (lambda () two notations are equivalent in all respects. (if (g) ’a =⇒ a (let ((x (h))) ’#(a b c) =⇒ #(a b c) x) ’() =⇒ () (and (g) (f)))) ’(+ 1 2) =⇒ (+ 1 2) ’(quote a) =⇒ (quote a) Note: Implementations may recognize that some non-tail calls, ’’a =⇒ (quote a) such as the call to h above, can be evaluated as though they Numerical constants, string constants, character constants, were tail calls. In the example above, the let expression could vector constants, bytevector constants, and boolean con- be compiled as a tail call to h. (The possibility of h return- stants evaluate to themselves; they need not be quoted. ing an unexpected number of values can be ignored, because in that case the effect of the let is explicitly unspecified and ’145932 =⇒ 145932 implementation-dependent.) 145932 =⇒ 145932 ’"abc" =⇒ "abc" "abc" =⇒ "abc" 4. Expressions ’# =⇒ # Expression types are categorized as primitive or derived. # =⇒ # Primitive expression types include variables and procedure ’#(a 10) =⇒ #(a 10) calls. Derived expression types are not semantically primi- #(a 10) =⇒ #(a 10) ’#u8(64 65) =⇒ #(64 65) tive, but can instead be defined as macros. Suitable syntax #u8(64 65) =⇒ #(64 65) definitions of some of the derived expressions are given in ’#t =⇒ #t section 7.3. #t =⇒ #t The procedures force, promise?, make-promise, and As noted in section 3.4, it is an error to attempt to alter make-parameter are also described in this chapter be- a constant (i.e. the value of a literal expression) using a cause they are intimately associated with the delay, mutation procedure like set-car! or string-set!. delay-force, and parameterize expression types.

4.1.3. Procedure calls 4.1. Primitive expression types (hoperatori hoperand i ... ) syntax 4.1.1. Variable references 1 A procedure call is written by enclosing in parentheses an hvariablei syntax expression for the procedure to be called followed by ex- pressions for the arguments to be passed to it. The op- An expression consisting of a variable (section 3.1) is a erator and operand expressions are evaluated (in an un- variable reference. The value of the variable reference is specified order) and the resulting procedure is passed the the value stored in the location to which the variable is resulting arguments. bound. It is an error to reference an unbound variable. (+ 3 4) =⇒ 7 (define x 28) ((if #f + *) 3 4) =⇒ 12 x =⇒ 28 The procedures in this document are available as the val- ues of variables exported by the standard libraries. For ex- 4.1.2. Literal expressions ample, the addition and multiplication procedures in the above examples are the values of the variables + and * in (quote hdatumi) syntax the base library. New procedures are created by evaluating ’hdatumi syntax lambda expressions (see section 4.1.4). hconstanti syntax Procedure calls can return any number of values (see (quote hdatumi) evaluates to hdatumi. hDatumi can be values in section 6.10). Most of the procedures defined any external representation of a Scheme object (see sec- in this report return one value or, for procedures such as 4. Expressions 13 apply, pass on the values returned by a call to one of their •h variablei: The procedure takes any number of argu- arguments. Exceptions are noted in the individual descrip- ments; when the procedure is called, the sequence of tions. actual arguments is converted into a newly allocated Note: In contrast to other dialects of Lisp, the order of list, and the list is stored in a fresh location that is evaluation is unspecified, and the operator expression and the bound to hvariablei. operand expressions are always evaluated with the same evalu- • (hvariable1i ... hvariableni . hvariablen+1i): If a ation rules. space-delimited period precedes the last variable, then Note: Although the order of evaluation is otherwise unspeci- the procedure takes n or more arguments, where n is fied, the effect of any concurrent evaluation of the operator and the number of formal arguments before the period (it operand expressions is constrained to be consistent with some is an error if there is not at least one). The value stored sequential order of evaluation. The order of evaluation may be in the binding of the last variable will be a newly allo- chosen differently for each procedure call. cated list of the actual arguments left over after all the other actual arguments have been matched up against Note: In many dialects of Lisp, the empty list, (), is a legiti- the other formal arguments. mate expression evaluating to itself. In Scheme, it is an error.

It is an error for a hvariablei to appear more than once in 4.1.4. Procedures hformalsi.

(lambda hformalsi hbodyi) syntax ((lambda x x) 3 4 5 6) =⇒ (3 4 5 6) ((lambda (x y . z) z) Syntax: hFormalsi is a formal arguments list as described 3 4 5 6) =⇒ (5 6) below, and hbodyi is a sequence of zero or more definitions followed by one or more expressions. 4.1.5. Conditionals Semantics: A lambda expression evaluates to a procedure. The environment in effect when the lambda expression was (if htesti hconsequenti halternatei) syntax evaluated is remembered as part of the procedure. When (if htesti hconsequenti) syntax the procedure is later called with some actual arguments, the environment in which the lambda expression was evalu- Syntax: hTesti, hconsequenti, and halternatei are expres- ated will be extended by binding the variables in the formal sions. argument list to fresh locations, and the corresponding ac- Semantics: An if expression is evaluated as follows: first, tual argument values will be stored in those locations. (A htesti is evaluated. If it yields a true value (see section 6.3), fresh location is one that is distinct from every previously then hconsequenti is evaluated and its values are returned. existing location.) Next, the expressions in the body of Otherwise halternatei is evaluated and its values are re- the lambda expression (which may contain definitions and turned. If htesti yields a false value and no halternatei is thus represent a letrec* form — see section 4.2.2) will be specified, then the result of the expression is unspecified. evaluated sequentially in the extended environment. The results of the last expression in the body will be returned (if (> 3 2) ’yes ’no) =⇒ yes as the results of the procedure call. (if (> 2 3) ’yes ’no) =⇒ no (if (> 3 2) (lambda (x) (+ x x)) =⇒ a procedure (- 3 2) ((lambda (x) (+ x x)) 4) =⇒ 8 (+ 3 2)) =⇒ 1

(define reverse-subtract (lambda (x y) (- y x))) 4.1.6. Assignments (reverse-subtract 7 10) =⇒ 3 (set! hvariablei hexpressioni) syntax (define add4 (let ((x 4)) Semantics: hExpressioni is evaluated, and the resulting (lambda (y) (+ x y)))) value is stored in the location to which hvariablei is bound. (add4 6) =⇒ 10 It is an error if hvariablei is not bound either in some region enclosing the set! expression or else globally. The result hFormalsi have one of the following forms: of the set! expression is unspecified.

• (hvariable1i ... ): The procedure takes a fixed num- (define x 2) ber of arguments; when the procedure is called, the (+ x 1) =⇒ 3 arguments will be stored in fresh locations that are (set! x 4) =⇒ unspecified bound to the corresponding variables. (+ x 1) =⇒ 5 14 Revised7 Scheme

4.1.7. Inclusion form, then the hexpressioni is evaluated. It is an error if its value is not a procedure that accepts one argument.

(include hstring1i hstring2i ... ) syntax This procedure is then called on the value of the htesti and (include-ci hstring1i hstring2i ... ) syntax the values returned by this procedure are returned by the cond expression. Both include and include-ci take one or more filenames expressed as string literals, apply an implementation- If all htestis evaluate to #f, and there is no else clause, specific algorithm to find corresponding files, read the con- then the result of the conditional expression is unspecified; tents of the files in the specified order as if by repeated if there is an else clause, then its hexpressionis are evaluated applications of read, and effectively replace the include in order, and the values of the last one are returned. or include-ci expression with a begin expression contain- (cond ((> 3 2) ’greater) ing what was read from the files. The difference between ((< 3 2) ’less)) =⇒ greater the two is that include-ci reads each file as if it began (cond ((> 3 3) ’greater) with the #!fold-case directive, while include does not. ((< 3 3) ’less) Note: Implementations are encouraged to search for files in (else ’equal)) =⇒ equal the directory which contains the including file, and to provide (cond ((assv ’b ’((a 1) (b 2))) => cadr) =⇒ a way for users to specify other directories to search. (else #f)) 2 Note: For portability, include and include-ci must operate on source files. Their operation on other kinds of files necessarily (case hkeyi hclause1i hclause2i ... ) syntax varies among implementations. Syntax: hKeyi can be any expression. Each hclausei has the form

4.2. Derived expression types ((hdatum1i ... ) hexpression1i hexpression2i ... ), where each hdatumi is an external representation of some The constructs in this section are hygienic, as discussed object. It is an error if any of the hdatumis are the same in section 4.3. For reference purposes, section 7.3 gives anywhere in the expression. Alternatively, a hclausei can syntax definitions that will convert most of the constructs be of the form described in this section into the primitive constructs de- ((hdatum i ... ) => hexpressioni) scribed in the previous section. 1 The last hclausei can be an “else clause,” which has one of the forms 4.2.1. Conditionals (else hexpression1i hexpression2i ... )

(cond hclause1i hclause2i ... ) syntax else auxiliary syntax or => auxiliary syntax (else => hexpressioni). Syntax: hClausesi take one of two forms, either Semantics: A case expression is evaluated as follows. (htesti hexpression1i ... ) hKeyi is evaluated and its result is compared against each where htesti is any expression, or hdatumi. If the result of evaluating hkeyi is the same (in the sense of eqv?; see section 6.1) to a hdatumi, then the (htesti => hexpressioni) expressions in the corresponding hclausei are evaluated in The last hclausei can be an “else clause,” which has the order and the results of the last expression in the hclausei form are returned as the results of the case expression. (else hexpression1i hexpression2i ... ). If the result of evaluating hkeyi is different from every Semantics: A cond expression is evaluated by evaluating hdatumi, then if there is an else clause, its expressions are the htesti expressions of successive hclauseis in order until evaluated and the results of the last are the results of the one of them evaluates to a true value (see section 6.3). case expression; otherwise the result of the case expres- When a htesti evaluates to a true value, the remaining sion is unspecified. hexpressionis in its hclausei are evaluated in order, and the If the selected hclausei or else clause uses the => alternate results of the last hexpressioni in the hclausei are returned form, then the hexpressioni is evaluated. It is an error if as the results of the entire cond expression. its value is not a procedure accepting one argument. This If the selected hclausei contains only the htesti and no procedure is then called on the value of the hkeyi and the hexpressionis, then the value of the htesti is returned as values returned by this procedure are returned by the case the result. If the selected hclausei uses the => alternate expression. 4. Expressions 15

(case (* 2 3) (unless (= 1 1.0) ((2 3 5 7) ’prime) (display "1") ((1 4 6 8 9) ’composite)) =⇒ composite (display "2")) =⇒ unspecified (case (car ’(c d)) and prints nothing ((a) ’a) ((b) ’b)) =⇒ unspecified (case (car ’(c d)) (cond-expand hce-clause1i hce-clause2i ... ) syntax ((a e i o u) ’vowel) The cond-expand expression type provides a way to stati- ((w y) ’semivowel) cally expand different expressions depending on the imple- (else => (lambda (x) x))) =⇒ c mentation. A hce-clausei takes the following form: (hfeature requirementi hexpressioni ... ) (and htest i ... ) syntax 1 The last clause can be an “else clause,” which has the form Semantics: The htesti expressions are evaluated from left (else hexpressioni ... ) to right, and if any expression evaluates to #f (see sec- tion 6.3), then #f is returned. Any remaining expressions A hfeature requirementi takes one of the following forms: are not evaluated. If all the expressions evaluate to true values, the value of the last expression is returned. If there •h feature identifieri are no expressions, then #t is returned. • (library hlibrary namei) (and (= 2 2) (> 2 1)) =⇒ #t (and (= 2 2) (< 2 1)) =⇒ #f • (and hfeature requirementi ... ) (and 1 2 ’c ’(f g)) =⇒ (f g) (and) =⇒ #t • (or hfeature requirementi ... ) • (not hfeature requirementi)

(or htest1i ... ) syntax Each implementation maintains a list of feature identifiers Semantics: The htesti expressions are evaluated from left which are present, as well as a list of libraries which can be to right, and the value of the first expression that evaluates imported. The value of a hfeature requirementi is deter- to a true value (see section 6.3) is returned. Any remaining mined by replacing each hfeature identifieri and (library expressions are not evaluated. If all expressions evaluate hlibrary namei) on the implementation’s lists with #t, and to #f or if there are no expressions, then #f is returned. all other feature identifiers and library names with #f, then (or (= 2 2) (> 2 1)) =⇒ #t evaluating the resulting expression as a Scheme boolean ex- (or (= 2 2) (< 2 1)) =⇒ #t pression under the normal interpretation of and, or, and (or #f #f #f) =⇒ #f not. (or (memq ’b ’(a b c)) (/ 3 0)) =⇒ (b c) A cond-expand is then expanded by evaluating the hfeature requirementis of successive hce-clauseis in order until one of them returns #t. When a true clause is found, (when htesti hexpression1i hexpression2i ... ) syntax the corresponding hexpressionis are spliced into the cur- Syntax: The htesti is an expression. rent context as if by begin, and the remaining clauses are ignored. If none of the hfeature requirementis evaluate to Semantics: The test is evaluated, and if it evaluates to #t, then if there is an else clause, its hexpressionis are in- a true value, the expressions are evaluated in order. The cluded. Otherwise, the cond-expand has no effect. Unlike result of the when expression is unspecified. cond, cond-expand does not depend on the value of any (when (= 1 1.0) variables. (display "1") The exact features provided are implementation-defined, (display "2")) =⇒ unspecified but for portability a core set of features is given in ap- and prints 12 pendix B.

(unless htesti hexpression1i hexpression2i ... ) syntax 4.2.2. Binding constructs Syntax: The htesti is an expression. The binding constructs let, let*, letrec, letrec*, Semantics: The test is evaluated, and if it evaluates to #f, let-values, and let*-values give Scheme a block struc- the expressions are evaluated in order. The result of the ture, like Algol 60. The syntax of the first four constructs unless expression is unspecified. is identical, but they differ in the regions they establish 16 Revised7 Scheme for their variable bindings. In a let expression, the initial (letrec hbindingsi hbodyi) syntaxSyntax: hBindingsi values are computed before any of the variables become has the form bound; in a let* expression, the bindings and evaluations ((hvariable1i hinit1i) ... ), are performed sequentially; while in letrec and letrec* expressions, all the bindings are in effect while their initial and hbodyi is a sequence of zero or more definitions fol- values are being computed, thus allowing mutually recur- lowed by one or more expressions as described in sec- sive definitions. The let-values and let*-values con- tion 4.1.4. It is an error for a hvariablei to appear more structs are analogous to let and let* respectively, but than once in the list of variables being bound. are designed to handle multiple-valued expressions, bind- Semantics: The hvariableis are bound to fresh locations ing different identifiers to each returned value. holding unspecified values, the hinitis are evaluated in the resulting environment (in some unspecified order), each (let hbindingsi hbodyi) syntax hvariablei is assigned to the result of the corresponding hiniti, the hbodyi is evaluated in the resulting environment, Syntax: hBindingsi has the form and the values of the last expression in hbodyi are returned. ((hvariable1i hinit1i) ... ), Each binding of a hvariablei has the entire letrec expres- where each hiniti is an expression, and hbodyi is a sequence sion as its region, making it possible to define mutually of zero or more definitions followed by a sequence of one recursive procedures. or more expressions as described in section 4.1.4. It is an (letrec ((even? error for a hvariablei to appear more than once in the list (lambda (n) of variables being bound. (if (zero? n) #t Semantics: The hinitis are evaluated in the current envi- (odd? (- n 1))))) ronment (in some unspecified order), the hvariableis are (odd? bound to fresh locations holding the results, the hbodyi is (lambda (n) evaluated in the extended environment, and the values of (if (zero? n) the last expression of hbodyi are returned. Each binding #f of a hvariablei has hbodyi as its region. (even? (- n 1)))))) (even? 88)) (let ((x 2) (y 3)) =⇒ #t (* x y)) =⇒ 6 One restriction on letrec is very important: if it is not (let ((x 2) (y 3)) possible to evaluate each hiniti without assigning or refer- (let ((x 7) ring to the value of any hvariablei, it is an error. The (z (+ x y))) restriction is necessary because letrec is defined in terms (* z x))) =⇒ 35 of a procedure call where a lambda expression binds the See also “named let,” section 4.2.4. hvariableis to the values of the hinitis. In the most com- mon uses of letrec, all the hinitis are lambda expressions and the restriction is satisfied automatically. Another re- (let* hbindingsi hbodyi) syntax striction is that the continuation of a hiniti should not be Syntax: hBindingsi has the form invoked more than once.

((hvariable1i hinit1i) ... ), and hbodyi is a sequence of zero or more definitions fol- (letrec* hbindingsi hbodyi) syntax lowed by one or more expressions as described in sec- Syntax: hBindingsi has the form tion 4.1.4. ((hvariable1i hinit1i) ... ), Semantics: The let* binding construct is similar to let, but the bindings are performed sequentially from left to and hbodyi is a sequence of zero or more definitions fol- right, and the region of a binding indicated by (hvariablei lowed by one or more expressions as described in sec- hiniti) is that part of the let* expression to the right of tion 4.1.4. It is an error for a hvariablei to appear more the binding. Thus the second binding is done in an en- than once in the list of variables being bound. vironment in which the first binding is visible, and so on. Semantics: The hvariableis are bound to fresh locations, The hvariableis need not be distinct. each hvariablei is assigned in left-to-right order to the re- (let ((x 2) (y 3)) sult of evaluating the corresponding hiniti, the hbodyi is (let* ((x 7) evaluated in the resulting environment, and the values of (z (+ x y))) the last expression in hbodyi are returned. Despite the left- (* z x))) =⇒ 70 to-right evaluation and assignment order, each binding of a 4. Expressions 17 hvariablei has the entire letrec* expression as its region, Semantics: The let*-values construct is similar to making it possible to define mutually recursive procedures. let-values, but the hinitis are evaluated and bindings cre- ated sequentially from left to right, with the region of the If it is not possible to evaluate each hiniti without assigning bindings of each hformalsi including the hinitis to its right or referring to the value of the corresponding hvariablei as well as hbodyi. Thus the second hiniti is evaluated in or the hvariablei of any of the bindings that follow it in an environment in which the first set of bindings is visible hbindingsi, it is an error. and initialized, and so on. (letrec* ((p (let ((a ’a) (b ’b) (x ’x) (y ’y)) (lambda (x) (let*-values (((a b) (values x y)) (+ 1 (q (- x 1))))) ((x y) (values a b))) (q (list a b x y))) =⇒ (x y x y) (lambda (y) (if (zero? y) 0 4.2.3. Sequencing (+ 1 (p (- y 1)))))) (x (p 5)) Both of Scheme’s sequencing constructs are named begin, (y x)) but the two have slightly different forms and uses: y) =⇒ 5 (begin hexpression or definitioni ... ) syntax This form of begin can appear as part of a hbodyi, or (let-values hmv-bindingsi hbodyi) syntax at the outermost level of a hprogrami, or at the REPL, Syntax: hMv-bindingsi has the form or directly nested in a begin that is itself of this form. It causes the contained expressions and definitions to be ((hformals1i hinit1i) ... ), evaluated exactly as if the enclosing begin construct were where each hiniti is an expression, and hbodyi is zero or not present. more definitions followed by a sequence of one or more Rationale: This form is commonly used in the output of macros expressions as described in section 4.1.4. It is an error for (see section 4.3) which need to generate multiple definitions and a variable to appear more than once in the set of hformalsi. splice them into the context in which they are expanded. Semantics: The hinitis are evaluated in the current en- vironment (in some unspecified order) as if by invoking (begin hexpression1i hexpression2i ... ) syntax call-with-values, and the variables occurring in the This form of can be used as an ordinary expression. hformalsi are bound to fresh locations holding the values begin The hexpressionis are evaluated sequentially from left to returned by the hinitis, where the hformalsi are matched right, and the values of the last hexpressioni are returned. to the return values in the same way that the hformalsi This expression type is used to sequence side effects such in a lambda expression are matched to the arguments in as assignments or input and output. a procedure call. Then, the hbodyi is evaluated in the ex- tended environment, and the values of the last expression (define x 0) of hbodyi are returned. Each binding of a hvariablei has hbodyi as its region. (and (= x 0) (begin (set! x 5) It is an error if the hformalsi do not match the number of (+ x 1))) =⇒ 6 values returned by the corresponding hiniti. (begin (display "4 plus 1 equals ") (let-values (((root rem) (exact-integer-sqrt 32))) (display (+ 4 1))) =⇒ unspecified (* root rem)) =⇒ 35 and prints 4 plus 1 equals 5

(let*-values hmv-bindingsi hbodyi) syntax 4.2.4. Iteration Syntax: hMv-bindingsi has the form (do ((hvariable1i hinit1i hstep1i) syntax ((hformalsi hiniti) ... ), ... ) htesti hexpressioni ... and hbodyi is a sequence of zero or more definitions fol- ( ) hcommandi ... lowed by one or more expressions as described in sec- ) tion 4.1.4. In each hformalsi, it is an error if any variable Syntax: All of hiniti, hstepi, htesti, and hcommandi are appears more than once. expressions. 18 Revised7 Scheme

Semantics: A do expression is an iteration construct. It (cons (car numbers) nonneg) specifies a set of variables to be bound, how they are to be neg)) initialized at the start, and how they are to be updated on ((< (car numbers) 0) each iteration. When a termination condition is met, the (loop (cdr numbers) loop exits after evaluating the hexpressionis. nonneg (cons (car numbers) neg))))) A do expression is evaluated as follows: The hiniti ex- =⇒ ((6 1 3) (-5 -2)) pressions are evaluated (in some unspecified order), the hvariableis are bound to fresh locations, the results of the hiniti expressions are stored in the bindings of the 4.2.5. Delayed evaluation hvariableis, and then the iteration phase begins. Each iteration begins by evaluating htesti; if the result is (delay hexpressioni) lazy library syntax false (see section 6.3), then the hcommandi expressions are Semantics: The delay construct is used together with evaluated in order for effect, the hstepi expressions are eval- the procedure force to implement lazy evaluation or call uated in some unspecified order, the hvariableis are bound by need. (delay hexpressioni) returns an object called a to fresh locations, the results of the hstepis are stored in the promise which at some point in the future can be asked (by bindings of the hvariableis, and the next iteration begins. the force procedure) to evaluate hexpressioni, and deliver the resulting value. The effect of hexpressioni returning If htesti evaluates to a true value, then the hexpressionis multiple values is unspecified. are evaluated from left to right and the values of the last hexpressioni are returned. If no hexpressionis are present, then the value of the do expression is unspecified. (delay-force hexpressioni) lazy library syntax The region of the binding of a hvariablei consists of the Semantics: The expression (delay-force expression) is entire do expression except for the hinitis. It is an error conceptually similar to (delay (force expression)), with for a hvariablei to appear more than once in the list of do the difference that forcing the result of delay-force will variables. in effect result in a tail call to (force expression), while A hstepi can be omitted, in which case the effect is the forcing the result of (delay (force expression)) might same as if (hvariablei hiniti hvariablei) had been written not. Thus iterative lazy algorithms that might result in a instead of (hvariablei hiniti). long series of chains of delay and force can be rewritten using delay-force to prevent consuming unbounded space (do ((vec (make-vector 5)) during evaluation. (i 0 (+ i 1))) ((= i 5) vec) (vector-set! vec i i)) =⇒ #(0 1 2 3 4) (force promise) lazy library procedure The force procedure forces the value of a promise created (let ((x ’(1 3 5 7 9))) by delay, delay-force, or make-promise. If no value has (do ((x x (cdr x)) (sum 0 (+ sum (car x)))) been computed for the promise, then a value is computed ((null? x) sum))) =⇒ 25 and returned. The value of the promise must be cached (or “memoized”) so that if it is forced a second time, the previously computed value is returned. Consequently, a (let hvariablei hbindingsi hbodyi) syntax delayed expression is evaluated using the parameter values and exception handler of the call to force which first re- Semantics: “Named let” is a variant on the syntax of quested its value. If promise is not a promise, it may be let which provides a more general looping construct than returned unchanged. do and can also be used to express recursion. It has the same syntax and semantics as ordinary let except that (force (delay (+ 1 2))) =⇒ 3 hvariablei is bound within hbodyi to a procedure whose (let ((p (delay (+ 1 2)))) formal arguments are the bound variables and whose body (list (force p) (force p))) is hbodyi. Thus the execution of hbodyi can be repeated =⇒ (3 3) by invoking the procedure named by hvariablei. (define integers (let loop ((numbers ’(3 -2 1 6 -5)) (letrec ((next (nonneg ’()) (lambda (n) (neg ’())) (delay (cons n (next (+ n 1))))))) (cond ((null? numbers) (list nonneg neg)) (next 0))) ((>= (car numbers) 0) (define head (loop (cdr numbers) (lambda (stream) (car (force stream)))) 4. Expressions 19

(define tail (eqv? (delay 1) 1) =⇒ unspecified (lambda (stream) (cdr (force stream)))) (pair? (delay (cons 1 2))) =⇒ unspecified

(head (tail (tail integers))) • Implementations may implement “implicit forcing,” =⇒ 2 where the value of a promise is forced by procedures The following example is a mechanical transformation of that operate only on arguments of a certain type, like a lazy stream-filtering algorithm into Scheme. Each call cdr and *. However, procedures that operate uni- to a constructor is wrapped in delay, and each argument formly on their arguments, like list, must not force passed to a deconstructor is wrapped in force. The use them. of (delay-force ...) instead of (delay (force ...)) around the body of the procedure ensures that an ever- (+ (delay (* 3 7)) 13) =⇒ unspecified growing sequence of pending promises does not exhaust (car available storage, because force will in effect force such (list (delay (* 3 7)) 13))=⇒ a promise sequences iteratively. (define (stream-filter p? s) (delay-force (promise? obj ) lazy library procedure (if (null? (force s)) (delay ’()) The promise? procedure returns #t if its argument is a (let ((h (car (force s))) promise, and #f otherwise. Note that promises are not (t (cdr (force s)))) necessarily disjoint from other Scheme types such as pro- (if (p? h) cedures. (delay (cons h (stream-filter p? t))) (stream-filter p? t)))))) (make-promise obj ) lazy library procedure (head (tail (tail (stream-filter odd? integers)))) =⇒ 5 The make-promise procedure returns a promise which, when forced, will return obj . It is similar to delay, but The following examples are not intended to illustrate good does not delay its argument: it is a procedure rather than programming style, as delay, force, and delay-force syntax. If obj is already a promise, it is returned. are mainly intended for programs written in the functional style. However, they do illustrate the property that only one value is computed for a promise, no matter how many 4.2.6. Dynamic bindings times it is forced. The dynamic extent of a procedure call is the time be- tween when it is initiated and when it returns. In Scheme, (define count 0) (section 6.10) allows (define p call-with-current-continuation (delay (begin (set! count (+ count 1)) reentering a dynamic extent after its procedure call has re- (if (> count x) turned. Thus, the dynamic extent of a call might not be a count single, continuous time period. (force p))))) This sections introduces parameter objects, which can be (define x 5) bound to new values for the duration of a dynamic extent. p =⇒ a promise (force p) =⇒ 6 The set of all parameter bindings at a given time is called p =⇒ a promise, still the dynamic environment. (begin (set! x 10) (force p)) =⇒ 6 (make-parameter init) procedure Various extensions to this semantics of delay, force and (make-parameter init converter) procedure are supported in some implementations: delay-force Returns a newly allocated parameter object, which is a pro- cedure that accepts zero arguments and returns the value • Calling force on an object that is not a promise may associated with the parameter object. Initially, this value simply return the object. is the value of (converter init), or of init if the conversion procedure converter is not specified. The associated value • It may be the case that there is no means by which can be temporarily changed using parameterize, which is a promise can be operationally distinguished from its described below. forced value. That is, expressions like the following may evaluate to either #t or to #f, depending on the The effect of passing arguments to a parameter object is implementation: implementation-dependent. 20 Revised7 Scheme

(parameterize ((hparam1i hvalue1i) ... ) syntax Semantics: The hbodyi is evaluated with an exception han- hbodyi) dler that binds the raised object (see raise in section 6.11) to hvariablei and, within the scope of that binding, evalu- Syntax: Both hparam1i and hvalue1i are expressions. ates the clauses as if they were the clauses of a cond ex- Semantics: A parameterize expression is used to change pression. That implicit cond expression is evaluated with the values returned by specified parameter objects during the continuation and dynamic environment of the guard the evaluation of the body. It is an error if the value of any expression. If every hcond clausei’s htesti evaluates to #f hparami expression is not a parameter object. and there is no else clause, then raise-continuable is The hparami and hvaluei expressions are evaluated in an invoked on the raised object within the dynamic environ- unspecified order. The hbodyi is evaluated in a dynamic ment of the original call to raise or raise-continuable, environment in which calls to the parameters return the except that the current exception handler is that of the results of passing the corresponding values to the conver- guard expression. sion procedure specified when the parameters were created. See section 6.11 for a more complete discussion of excep- Then the previous values of the parameters are restored tions. without passing them to the conversion procedure. The results of the last expression in the hbodyi are returned as (guard (condition the results of the entire parameterize expression. ((assq ’a condition) => cdr) Note: If the conversion procedure is not idempotent, the results ((assq ’b condition))) of (parameterize ((x (x))) ...), which appears to bind the (raise (list (cons ’a 42)))) parameter x to its current value, might not be what the user =⇒ 42 expects. (guard (condition If an implementation supports multiple threads of execu- ((assq ’a condition) => cdr) tion, then parameterize must not change the associated ((assq ’b condition))) values of any parameters in any thread other than the cur- (raise (list (cons ’b 23)))) rent thread and threads created inside hbodyi. =⇒ (b . 23) Parameter objects can be used to specify configurable set- tings for a computation without the need to pass the value to every procedure in the call chain explicitly. 4.2.8. Quasiquotation (define radix (make-parameter (quasiquote hqq templatei) syntax 10 `hqq templatei syntax (lambda (x) unquote auxiliary syntax (if (and (integer? x) (<= 2 x 16)) unquote-splicing auxiliary syntax x (error "invalid radix"))))) “Quasiquote” expressions are useful for constructing a list or vector structure when some but not all of the desired (define (f n) (number->string n (radix))) structure is known in advance. If no commas appear within the hqq templatei, the result of evaluating `hqq templatei (f 12) =⇒ "12" is equivalent to the result of evaluating ’hqq templatei. If (parameterize ((radix 2)) (f 12)) =⇒ "1100" a comma appears within the hqq templatei, however, the (f 12) =⇒ "12" expression following the comma is evaluated (“unquoted”) and its result is inserted into the structure instead of the (radix 16) =⇒ unspecified comma and the expression. If a comma appears followed without intervening whitespace by a commercial at-sign (parameterize ((radix 0)) (@), then it is an error if the following expression does not (f 12)) =⇒ error evaluate to a list; the opening and closing parentheses of the list are then “stripped away” and the elements of the 4.2.7. Exception handling list are inserted in place of the comma at-sign expression sequence. A comma at-sign should only appear within a (guard (hvariablei syntax list or vector hqq templatei. hcond clause1i hcond clause2i ... ) Note: In order to unquote an identifier beginning with @, it is hbodyi) necessary to use either an explicit unquote or to put whitespace Syntax: Each hcond clausei is as in the specification of after the comma, to avoid colliding with the comma at-sign cond. sequence. 4. Expressions 21

`(list ,(+ 1 2) 4) =⇒ (list 3 4) 4.2.9. Case-lambda (let ((name ’a)) `(list ,name ’,name)) =⇒ (list a (quote a)) (case-lambda hclausei ... ) case-lambda library syntax `(a ,(+ 1 2) ,@(map abs ’(4 -5 6)) b) =⇒ (a 3 4 5 6 b) Syntax: Each hclausei is of the form (hformalsi hbodyi), `(( foo ,(- 10 3)) ,@(cdr ’(c)) . ,(car ’(cons))) where hformalsi and hbodyi have the same syntax as in a =⇒ ((foo 7) . cons) lambda expression. `#(10 5 ,(sqrt 4) ,@(map sqrt ’(16 9)) 8) Semantics: A expression evaluates to a pro- =⇒ #(10 5 2 4 3 8) case-lambda (let ((foo ’(foo bar)) (@baz ’baz)) cedure that accepts a variable number of arguments and `(list ,@foo , @baz)) is lexically scoped in the same manner as a procedure re- =⇒ (foo bar baz) sulting from a lambda expression. When the procedure is called, the first hclausei for which the arguments agree Quasiquote expressions may be nested. Substitutions are with hformalsi is selected, where agreement is specified as made only for unquoted components appearing at the same for the hformalsi of a lambda expression. The variables nesting level as the outermost quasiquote. The nesting of hformalsi are bound to fresh locations, the values of level increases by one inside each successive quasiquotation, the arguments are stored in those locations, the hbodyi and decreases by one inside each unquotation. is evaluated in the extended environment, and the results `(a `(b ,(+ 1 2) ,(foo ,(+ 1 3) d) e) f) of hbodyi are returned as the results of the procedure call. =⇒ (a `(b ,(+ 1 2) ,(foo 4 d) e) f) It is an error for the arguments not to agree with the (let ((name1 ’x) hformalsi of any hclausei. (name2 ’y)) `(a `(b ,,name1 ,’,name2 d) e)) (define range =⇒ (a `(b ,x ,’y d) e) (case-lambda ((e) (range 0 e)) A quasiquote expression may return either newly allocated, ((b e) (do ((r ’() (cons e r)) mutable objects or literal structure for any structure that (e (- e 1) (- e 1))) is constructed at run time during the evaluation of the ((< e b) r))))) expression. Portions that do not need to be rebuilt are always literal. Thus, (range 3) =⇒ (0 1 2) (range 3 5) =⇒ (3 4) (let ((a 3)) `((1 2) ,a ,4 ,’five 6)) may be treated as equivalent to either of the following ex- pressions: 4.3. Macros

`((1 2) 3 4 five 6) Scheme programs can define and use new derived expres- sion types, called macros. Program-defined expression (let ((a 3)) types have the syntax (cons ’(1 2) (cons a (cons 4 (cons ’five ’(6)))))) (hkeywordi hdatumi ...) where hkeywordi is an identifier that uniquely determines However, it is not equivalent to this expression: the expression type. This identifier is called the syntactic (let ((a 3)) (list (list 1 2) a 4 ’five 6)) keyword, or simply keyword, of the macro. The number of the hdatumis, and their syntax, depends on the expression The two notations `hqq templatei and (quasiquote type. hqq templatei) are identical in all respects. ,hexpressioni is identical to (unquote hexpressioni), and ,@hexpressioni Each instance of a macro is called a use of the macro. The is identical to (unquote-splicing hexpressioni). The set of rules that specifies how a use of a macro is transcribed write procedure may output either format. into a more primitive expression is called the transformer of the macro. (quasiquote (list (unquote (+ 1 2)) 4)) =⇒ (list 3 4) The macro definition facility consists of two parts: ’(quasiquote (list (unquote (+ 1 2)) 4)) =⇒ `(list ,(+ 1 2) 4) • A set of expressions used to establish that certain iden- i.e., (quasiquote (list (unquote (+ 1 2)) 4)) tifiers are macro keywords, associate them with macro transformers, and control the scope within which a It is an error if any of the identifiers quasiquote, macro is defined, and unquote, or unquote-splicing appear in positions within a hqq templatei otherwise than as described above. • a pattern language for specifying macro transformers. 22 Revised7 Scheme

The syntactic keyword of a macro may shadow variable bindings, and local variable bindings may shadow syntac- (let ((x ’outer)) tic bindings. Two mechanisms are provided to prevent (let-syntax ((m (syntax-rules () ((m) x)))) unintended conflicts: (let ((x ’inner)) (m)))) =⇒ outer • If a macro transformer inserts a binding for an identi- fier (variable or keyword), the identifier will in effect be (letrec-syntax hbindingsi hbodyi) syntax renamed throughout its scope to avoid conflicts with other identifiers. Note that a global variable definition Syntax: Same as for let-syntax. may or may not introduce a binding; see section 5.3. Semantics: The hbodyi is expanded in the syntactic environment obtained by extending the syntactic envi- • If a macro transformer inserts a free reference to an ronment of the letrec-syntax expression with macros identifier, the reference refers to the binding that was whose keywords are the hkeywordis, bound to the speci- visible where the transformer was specified, regard- fied transformers. Each binding of a hkeywordi has the less of any local bindings that surround the use of the htransformer specis as well as the hbodyi within its region, macro. so the transformers can transcribe expressions into uses of the macros introduced by the letrec-syntax expression. In consequence, all macros defined using the pattern lan- guage are “hygienic” and “referentially transparent” and (letrec-syntax thus preserve Scheme’s lexical scoping. [21, 22, 4, 11, 15] ((my-or (syntax-rules () ((my-or) #f) Implementations may provide macro facilities of other ((my-or e) e) types. ((my-or e1 e2 ...) (let ((temp e1)) (if temp 4.3.1. Binding constructs for syntactic keywords temp (my-or e2 ...))))))) The let-syntax and letrec-syntax binding constructs (let ((x #f) are analogous to let and letrec, but they bind syntactic (y 7) keywords to macro transformers instead of binding vari- (temp 8) ables to locations that contain values. Syntactic keywords (let odd?) can also be bound globally or locally with define-syntax; (if even?)) see section 5.4. (my-or x (let temp) (if y) (let-syntax hbindingsi hbodyi) syntax y))) =⇒ 7 Syntax: hBindingsi has the form ((hkeywordi htransformer speci) ... ) 4.3.2. Pattern language Each hkeywordi is an identifier, each htransformer speci is A htransformer speci has one of the following forms: an instance of syntax-rules, and hbodyi is a sequence of one or more definitions followed by one or more expressions. It is an error for a hkeywordi to appear more than once in (syntax-rules (hliterali ... ) syntax the list of keywords being bound. hsyntax rulei ... ) Semantics: The hbodyi is expanded in the syntactic envi- (syntax-rules hellipsisi (hliterali ... ) syntax ronment obtained by extending the syntactic environment hsyntax rulei ... ) of the let-syntax expression with macros whose keywords auxiliary syntax are the hkeywordis, bound to the specified transformers. ... auxiliary syntax Each binding of a hkeywordi has hbodyi as its region. Syntax: It is an error if any of the hliteralis, or the hellipsisi in the second form, is not an identifier. It is also an error (let-syntax ((when (syntax-rules () if hsyntax rulei is not of the form ((when test stmt1 stmt2 ...) (if test (hpatterni htemplatei) (begin stmt1 The hpatterni in a hsyntax rulei is a list hpatterni whose stmt2 ...)))))) first element is an identifier. (let ((if #t)) (when if (set! if ’now)) A hpatterni is either an identifier, a constant, or one of the if)) =⇒ now following 4. Expressions 23

(hpatterni ...) More formally, an input expression E matches a pattern P (hpatterni hpatterni ... . hpatterni) if and only if: (hpatterni ... hpatterni hellipsisi hpatterni ...) (hpatterni ... hpatterni hellipsisi hpatterni ... . hpatterni) • P is an underscore ( ). #(hpatterni ...) #(hpatterni ... hpatterni hellipsisi hpatterni ...) • P is a non-literal identifier; or and a htemplatei is either an identifier, a constant, or one • P is a literal identifier and E is an identifier with the of the following same binding; or (helementi ...) (helementi helementi ... . htemplatei) • P is a list (P1 ...Pn) and E is a list of n elements (hellipsisi htemplatei) that match P1 through Pn, respectively; or #(helementi ...) • P is an improper list (P P ...P . P ) and where an helementi is a htemplatei optionally followed by 1 2 n n+1 E is a list or improper list of n or more elements that an hellipsisi. An hellipsisi is the identifier specified in the match P through P , respectively, and whose nth tail second form of syntax-rules, or the default identifier ... 1 n matches P ; or (three consecutive periods) otherwise. n+1

Semantics: An instance of syntax-rules produces a new • P is of the form (P1 ...Pk Pe hellipsisi Pm+1 ... macro transformer by specifying a sequence of hygienic Pn) where E is a proper list of n elements, the first rewrite rules. A use of a macro whose keyword is associated k of which match P1 through Pk, respectively, whose with a transformer specified by syntax-rules is matched next m − k elements each match Pe, whose remaining against the patterns contained in the hsyntax ruleis, be- n − m elements match Pm+1 through Pn; or ginning with the leftmost hsyntax rulei. When a match is found, the macro use is transcribed hygienically according • P is of the form (P1 ...Pk Pe hellipsisi Pm+1 ... to the template. Pn . Px) where E is a list or improper list of n el- ements, the first k of which match P through P , An identifier appearing within a hpatterni can be an under- 1 k whose next m − k elements each match P , whose re- score ( ), a literal identifier listed in the list of hliteralis, e maining n−m elements match P through P , and or the hellipsisi. All other identifiers appearing within a m+1 n whose nth and final cdr matches P ; or hpatterni are pattern variables. x

The keyword at the beginning of the pattern in a • P is a vector of the form #(P1 ...Pn) and E is a hsyntax rulei is not involved in the matching and is con- vector of n elements that match P1 through Pn; or sidered neither a pattern variable nor a literal identifier. • P is of the form #(P1 ...Pk Pe hellipsisi Pm+1 Pattern variables match arbitrary input elements and are ...Pn) where E is a vector of n elements the first used to refer to elements of the input in the template. It k of which match P1 through Pk, whose next m − k is an error for the same pattern variable to appear more elements each match Pe, and whose remaining n − m than once in a hpatterni. elements match Pm+1 through Pn; or Underscores also match arbitrary input elements but are not pattern variables and so cannot be used to refer to • P is a constant and E is equal to P in the sense of the those elements. If an underscore appears in the hliteralis equal? procedure. list, then that takes precedence and underscores in the hpatterni match as literals. Multiple underscores may ap- It is an error to use a macro keyword, within the scope of pear in a hpatterni. its binding, in an expression that does not match any of Identifiers that appear in (hliterali ... ) are interpreted as the patterns. literal identifiers to be matched against corresponding el- When a macro use is transcribed according to the template ements of the input. An element in the input matches a of the matching hsyntax rulei, pattern variables that occur literal identifier if and only if it is an identifier and either in the template are replaced by the elements they match in both its occurrence in the macro expression and its occur- the input. Pattern variables that occur in subpatterns fol- rence in the macro definition have the same lexical binding, lowed by one or more instances of the identifier hellipsisi are or the two identifiers are the same and both have no lexical allowed only in subtemplates that are followed by as many binding. instances of hellipsisi. They are replaced in the output by A subpattern followed by hellipsisi can match zero or all of the elements they match in the input, distributed as more elements of the input, unless hellipsisi appears in the indicated. It is an error if the output cannot be built up hliteralis, in which case it is matched as a literal. as specified. 24 Revised7 Scheme

Identifiers that appear in the template but are not pattern macro, which can provide more descriptive error messages. variables or the identifier hellipsisi are inserted into the out- hmessagei is a string literal, and hargsi arbitrary expres- put as literal identifiers. If a literal identifier is inserted as a sions providing additional information. Applications can- free identifier then it refers to the binding of that identifier not count on being able to catch syntax errors with excep- within whose scope the instance of syntax-rules appears. tion handlers or guards. If a literal identifier is inserted as a bound identifier then (define-syntax simple-let it is in effect renamed to prevent inadvertent captures of (syntax-rules () free identifiers. (( (head ... ((x . y) val) . tail) A template of the form (hellipsisi htemplatei) is identical body1 body2 ...) to htemplatei, except that ellipses within the template have (syntax-error no special meaning. That is, any ellipses contained within "expected an identifier but got" htemplatei are treated as ordinary identifiers. In partic- (x . y))) (( ((name val) ...) body1 body2 ...) ular, the template (hellipsisi hellipsisi) produces a single ((lambda (name ...) body1 body2 ...) hellipsisi. This allows syntactic abstractions to expand into val ...)))) code containing ellipses. (define-syntax be-like-begin (syntax-rules () ((be-like-begin name) (define-syntax name (syntax-rules () ((name expr (...... )) (begin expr (...... ))))))))

(be-like-begin sequence) (sequence 1 2 3 4) =⇒ 4 As an example, if let and cond are defined as in section 7.3 then they are hygienic (as required) and the following is not an error. (let ((=> #f)) (cond (#t => ’ok))) =⇒ ok The macro transformer for cond recognizes => as a local variable, and hence an expression, and not as the base iden- tifier =>, which the macro transformer treats as a syntactic keyword. Thus the example expands into (let ((=> #f)) (if #t (begin => ’ok))) instead of (let ((=> #f)) (let ((temp #t)) (if temp (’ok temp)))) which would result in an invalid procedure call.

4.3.3. Signaling errors in macro transformers

(syntax-error hmessagei hargsi ... ) syntax syntax-error behaves similarly to error (6.11) except that implementations with an expansion pass separate from evaluation should signal an error as soon as syntax-error is expanded. This can be used as a syntax-rules htemplatei for a hpatterni that is an invalid use of the 5. Program structure 25

5. Program structure • (prefix himport seti hidentifieri)

5.1. Programs • (rename himport set1i (hidentifier1i hidentifier2i) ... ) A Scheme program consists of one or more import decla- rations followed by a sequence of expressions and defini- In the first form, all of the identifiers in the named library’s tions. Import declarations specify the libraries on which export clauses are imported with the same names (or the a program or library depends; a subset of the identifiers exported names if exported with rename). The additional exported by the libraries are made available to the pro- himport seti forms modify this set as follows: gram. Expressions are described in chapter 4. Definitions are either variable definitions, syntax definitions, or record- • only produces a subset of the given himport seti in- type definitions, all of which are explained in this chapter. cluding only the listed identifiers (after any renaming). They are valid in some, but not all, contexts where expres- It is an error if any of the listed identifiers are not sions are allowed, specifically at the outermost level of a found in the original set. hprogrami and at the beginning of a hbodyi. • except produces a subset of the given himport seti, At the outermost level of a program, (begin excluding the listed identifiers (after any renaming). hexpression or definition1i ... ) is equivalent to the It is an error if any of the listed identifiers are not sequence of expressions and definitions in the begin. Sim- found in the original set. ilarly, in a hbodyi, (begin hdefinition1i ... ) is equivalent • rename modifies the given himport seti, replacing each to the sequence hdefinition1i ... . Macros can expand into instance of hidentifier1i with hidentifier2i. It is an such begin forms. error if any of the listed hidentifier1is are not found Import declarations and definitions cause bindings to be in the original set. created in the global environment or modify the value of • prefix automatically renames all identifiers in the existing global bindings. The initial environment of a pro- given himport seti, prefixing each with the specified gram is empty, so at least one import declaration is needed hidentifieri. to introduce initial bindings. Expressions occurring at the outermost level of a program In a program or library declaration, it is an error to import do not create any bindings. They are executed in order the same identifier more than once with different bindings, when the program is invoked or loaded, and typically per- or to redefine or mutate an imported binding with a defi- form some kind of initialization. nition or with set!, or to refer to an identifier before it is Programs and libraries are typically stored in files, al- imported. However, a REPL should permit these actions. though in some implementations they can be entered inter- actively into a running Scheme system. Other paradigms 5.3. Variable definitions are possible. Implementations which store libraries in files should document the mapping from the name of a library A variable definition binds one or more identifiers and spec- to its location in the file system. ifies an initial value for each of them. It takes one of the following forms:

5.2. Import declarations • (define hvariablei hexpressioni) An import declaration takes the following form: • (define (hvariablei hformalsi) hbodyi) (import himport-seti ... ) hFormalsi are either a sequence of zero or more vari- ables, or a sequence of one or more variables followed by a space-delimited period and another variable (as An import declaration provides a way to import identifiers in a lambda expression). This form is equivalent to exported by a library. Each himport seti names a set of bindings from a library and possibly specifies local names (define hvariablei for the imported bindings. It takes one of the following (lambda (hformalsi) hbodyi)). forms: • (define (hvariablei . hformali) hbodyi) hFormali is a single variable. This form is equivalent •h library namei to • (only himport seti hidentifieri ... ) (define hvariablei • (except himport seti hidentifieri ... ) (lambda hformali hbodyi)). 26 Revised7 Scheme

5.3.1. Top level definitions Wherever an internal definition can occur, (begin hdefinition1i ... ) is equivalent to the sequence of defini- At the outermost level of a program, a definition tions that form the body of the begin. (define hvariablei hexpressioni) has essentially the same effect as the assignment expres- sion 5.3.3. Multiple-value definitions

(set! hvariablei hexpressioni) The construct define-values introduces new definitions if hvariablei is bound to a non-syntax value. However, if like define, but can create multiple definitions from a sin- hvariablei is not bound, or is bound to a syntax definition gle expression returning multiple values. It is allowed wher- (see below), then the definition will bind hvariablei to a ever define is allowed. new location before performing the assignment, whereas it would be an error to perform a set! on an unbound variable. (define-values hformalsi hexpressioni) syntax (define add3 It is an error if a variable appears more than once in the (lambda (x) (+ x 3))) set of hformalsi. (add3 3) =⇒ 6 Semantics: hExpressioni is evaluated, and the hformalsi (define first car) (first ’(1 2)) =⇒ 1 are bound to the return values in the same way that the hformalsi in a lambda expression are matched to the argu- ments in a procedure call. 5.3.2. Internal definitions (let () Definitions can occur at the beginning of a hbodyi (that (define-values (x y) (values 1 2)) is, the body of a lambda, let, let*, letrec, letrec*, (+ x y)) =⇒ 3 let-values, let*-values, let-syntax, letrec-syntax, parameterize, guard, or case-lambda). Note that such a body might not be apparent until after expansion of other syntax. Such definitions are known as internal definitions 5.4. Syntax definitions as opposed to the global definitions described above. The variable defined by an internal definition is local to the Syntax definitions have this form: hbodyi. That is, hvariablei is bound rather than assigned, and the region of the binding is the entire hbodyi. For (define-syntax hkeywordi htransformer speci) example, hKeywordi is an identifier, and the htransformer speci is (let ((x 5)) an instance of syntax-rules. Like variable definitions, (define foo (lambda (y) (bar x y))) syntax definitions may appear at the outermost level or (define bar (lambda (a b) (+ (* a b) a))) nested within a body. (foo (+ x 3))) =⇒ 45 If the define-syntax occurs at the outermost level, then An expanded hbodyi containing internal definitions (but the global syntactic environment is extended by binding not syntax definitions or record definitions) can always be the hkeywordi to the specified transformer, but previous converted into a completely equivalent letrec* expression. expansions of any global binding for hkeywordi remain un- For example, the let expression in the above example is changed. Otherwise, it is an internal syntax definition, and equivalent to is local to the hbodyi in which it is defined. Any use of a syntax keyword before its corresponding definition is an (let ((x 5)) (letrec* ((foo (lambda (y) (bar x y))) error. In particular, a use that precedes an inner definition (bar (lambda (a b) (+ (* a b) a)))) will not apply an outer definition. (foo (+ x 3)))) (let ((x 1) (y 2)) Just as for the equivalent letrec* expression, it is an er- (define-syntax swap! ror if it is not possible to evaluate each hexpressioni of (syntax-rules () every internal definition in a hbodyi without assigning or ((swap! a b) referring to the value of the corresponding hvariablei or the (let ((tmp a)) hvariablei of any of the definitions that follow it in hbodyi. (set! a b) (set! b tmp))))) It is an error to define the same identifier more than once (swap! x y) in the same hbodyi. (list x y)) =⇒ (2 1) 5. Program structure 27

Macros can expand into definitions in any context that An instance of define-record-type is equivalent to the permits them. However, it is an error for a definition to following definitions: define an identifier whose binding has to be known in or- der to determine the meaning of the definition itself, or of •h namei is bound to a representation of the record type any preceding definition that belongs to the same group itself. This may be a run-time object or a purely syn- of internal definitions. Similarly, it is an error for an in- tactic representation. The representation is not uti- ternal definition to define an identifier whose binding has lized in this report, but it serves as a means to identify to be known in order to determine the boundary between the record type for use by further language extensions. the internal definitions and the expressions of the body it belongs to. For example, the following are errors: •h constructor namei is bound to a procedure that takes (define define 3) as many arguments as there are hfield nameis in the (hconstructor namei ... ) subexpression and returns (begin (define begin list)) a new record of type hnamei. Fields whose names are listed with hconstructor namei have the corresponding (let-syntax argument as their initial value. The initial values of ((foo (syntax-rules () all other fields are unspecified. It is an error for a ((foo (proc args ...) body ...) field name to appear in hconstructori but not as a (define proc hfield namei. (lambda (args ...) body ...)))))) •h predi is bound to a predicate that returns #t when (let ((x 3)) given a value returned by the procedure bound to (foo (plus x y) (+ x y)) hconstructor namei and #f for everything else. (define foo x) (plus foo x))) • Each haccessor namei is bound to a procedure that takes a record of type hnamei and returns the cur- 5.5. Record-type definitions rent value of the corresponding field. It is an error to pass an accessor a value which is not a record of the appropriate type. Record-type definitions are used to introduce new data types, called record types. Like other definitions, they may • Each hmodifier namei is bound to a procedure that appear either at the outermost level or in a body. The val- takes a record of type hnamei and a value which be- ues of a record type are called records and are aggregations comes the new value of the corresponding field; an of zero or more fields, each of which holds a single loca- unspecified value is returned. It is an error to pass a tion. A predicate, a constructor, and field accessors and modifier a first argument which is not a record of the mutators are defined for each record type. appropriate type.

(define-record-type hnamei syntax For instance, the following record-type definition hconstructori hpredi hfieldi ... ) (define-record-type Syntax: hnamei and hpredi are identifiers. The (kons x y) hconstructori is of the form pare? (hconstructor namei hfield namei ... ) (x kar set-kar!) (y kdr)) and each hfieldi is either of the form (hfield namei haccessor namei) defines kons to be a constructor, kar and kdr to be ac- or of the form cessors, set-kar! to be a modifier, and pare? to be a (hfield namei haccessor namei hmodifier namei) predicate for instances of .

It is an error for the same identifier to occur more than once (pare? (kons 1 2)) =⇒ #t as a field name. It is also an error for the same identifier (pare? (cons 1 2)) =⇒ #f to occur more than once as an accessor or mutator name. (kar (kons 1 2)) =⇒ 1 The define-record-type construct is generative: each (kdr (kons 1 2)) =⇒ 2 use creates a new record type that is distinct from all exist- (let ((k (kons 1 2))) ing types, including Scheme’s predefined types and other (set-kar! k 3) (kar k)) =⇒ 3 record types — even record types of the same name or structure. 28 Revised7 Scheme

5.6. Libraries named by hidentifier1i in each (hidentifier1i hidentifier2i) pairing, using hidentifier2i as the external name. Libraries provide a way to organize Scheme programs into An import declaration provides a way to import the iden- reusable parts with explicitly defined interfaces to the rest tifiers exported by another library. It has the same syntax of the program. This section defines the notation and se- and semantics as an import declaration used in a program mantics for libraries. or at the REPL (see section 5.2).

The begin, include, and include-ci declarations are 5.6.1. Library Syntax used to specify the body of the library. They have the A library definition takes the following form: same syntax and semantics as the corresponding expres- sion types, except that begin may contain any library dec- (define-library hlibrary namei larations rather than just expressions. hlibrary declarationi ... ) The include-library-declarations declaration is sim- ilar to include except that the contents of the file are hlibrary namei is a list whose members are identifiers and spliced directly into the current library definition. This exact non-negative integers. It is used to identify the li- can be used, for example, to share the same export decla- brary uniquely when importing from other programs or ration among multiple libraries as a simple form of library libraries. Libraries whose first identifier is scheme are re- interface. served for use by this report and future versions of this report. Libraries whose first identifier is srfi are reserved The cond-expand declaration has the same syntax and se- for libraries implementing Scheme Requests for Implemen- mantics as the cond-expand expression type, except that tation. It is inadvisable, but not an error, for identifiers it may contain any library declarations rather than just in library names to contain any of the characters | \ ? * expressions. < " : > + [ ] / or control characters after escapes are expanded. One possible implementation of libraries is as follows: After all cond-expand library declarations are expanded, a new A hlibrary declarationi is any of: environment is constructed for the library consisting of all imported bindings. The expressions and declarations from • (export hexport speci ... ) all begin, include and include-ci library declarations are expanded in that environment in the order in which • (import himport seti ... ) they occur in the library. Alternatively, cond-expand and import declarations may be processed in left to right order • (begin hcommand or definitioni ... ) interspersed with the processing of expressions and declara- tions, with the environment growing as imported bindings • (include hfilename1i hfilename2i ... ) are added to it by each import declaration. • (include-ci hfilename1i hfilename2i ... ) When a library is loaded, its expressions are executed in • (include-library-declarations hfilename1i textual order. If a library’s definitions are referenced in hfilename2i ... ) the expanded form of a program or library body, then that library must be loaded before the expanded program or • (cond-expand hce-clause1i hce-clause2i ... ) library body is evaluated. This rule applies transitively. If a library is imported by more than one program or library, An export declaration specifies a list of identifiers which it may possibly be loaded additional times. can be made visible to other libraries or programs. An hexport speci takes one of the following forms: Similarly, during the expansion of a library, if a syntax keyword imported from a library is needed to expand the library, then the imported library must be visited before •h identifieri the expansion of the importing library.

• (rename hidentifier1i hidentifier2i) Regardless of the number of times that a library is loaded, each program or library that imports bindings from a li- In an hexport speci, an hidentifieri names a single bind- brary must do so from a single loading of that library, re- ing defined within or imported into the library, where the gardless of the number of import declarations in which it external name for the export is the same as the name of appears. That is, (import (only (foo) a)) followed by the binding within the library. A rename spec exports the (import (only (foo) b)) has the same effect as (import binding defined within or imported into the library and (only (foo) a b)). 5. Program structure 29

5.6.2. Library example (display "\x1B;[1H\x1B;[J") ; clear vt100 (each grid The following example shows how a program can be divided (lambda (i j v) into libraries plus a relatively small main program [18]. If (display (if v "*" " ")) the main program is entered into a REPL, it is not neces- (when (= j (- (cols grid) 1)) sary to import the base library. (newline))))) (define (life grid iterations) (define-library (example grid) (do ((i 0 (+ i 1)) (export make rows cols ref each (grid0 grid grid1) (rename put! set!)) (grid1 (make (rows grid) (cols grid)) (import (scheme base)) grid0)) (begin ((= i iterations)) ;; Create an NxM grid. (each grid0 (define (make n m) (lambda (j k v) (let ((grid (make-vector n))) (let ((a (life-alive? grid0 j k))) (do ((i 0 (+ i 1))) (set! grid1 j k a)))) ((= i n) grid) (life-print grid1))))) (let ((v (make-vector m #false))) (vector-set! grid i v))))) ;; Main program. (define (rows grid) (import (scheme base) (vector-length grid)) (only (example life) life) (define (cols grid) (rename (prefix (example grid) grid-) (vector-length (vector-ref grid 0))) (grid-make make-grid))) ;; Return #false if out of range. (define (ref grid n m) ;; Initialize a grid with a glider. (and (< -1 n (rows grid)) (define grid (make-grid 24 24)) (< -1 m (cols grid)) (grid-set! grid 1 1 #true) (vector-ref (vector-ref grid n) m))) (grid-set! grid 2 2 #true) (define (put! grid n m v) (grid-set! grid 3 0 #true) (vector-set! (vector-ref grid n) m v)) (grid-set! grid 3 1 #true) (define (each grid proc) (grid-set! grid 3 2 #true) (do ((j 0 (+ j 1))) ((= j (rows grid))) ;; Run for 80 iterations. (do ((k 0 (+ k 1))) (life grid 80) ((= k (cols grid))) (proc j k (ref grid j k)))))))

(define-library (example life) (export life) 5.7. The REPL (import (except (scheme base) set!) (scheme write) (example grid)) Implementations may provide an interactive session called (begin a REPL (Read-Eval-Print Loop), where import declara- (define (life-count grid i j) tions, expressions and definitions can be entered and eval- (define (count i j) uated one at a time. For convenience and ease of use, the (if (ref grid i j) 1 0)) global Scheme environment in a REPL must not be empty, (+ (count (- i 1) (- j 1)) but must start out with at least the bindings provided by (count (- i 1) j) the base library. This library includes the core syntax of (count (- i 1) (+ j 1)) Scheme and generally useful procedures that manipulate (count i (- j 1)) (count i (+ j 1)) data. For example, the variable abs is bound to a proce- (count (+ i 1) (- j 1)) dure of one argument that computes the absolute value of (count (+ i 1) j) a number, and the variable + is bound to a procedure that (count (+ i 1) (+ j 1)))) computes sums. The full list of (scheme base) bindings (define (life-alive? grid i j) can be found in Appendix A. (case (life-count grid i j) ((3) #true) Implementations are permitted to provide an initial REPL ((2) (ref grid i j)) environment which behaves as if all possible variables were (else #false))) bound to locations, most of which contained unspecified (define (life-print grid) values. Top level REPL definitions in such an implemen- 30 Revised7 Scheme tation are truly equivalent to assignments, unless the iden- • obj1 and obj2 are both inexact numbers such that they tifier is defined as a syntax keyword. are numerically equal (in the sense of =) and they An implementation may provide a mode of operation in yield the same results (in the sense of eqv?) when which the REPL reads its input from a file. Such a file passed as arguments to any other procedure that can is not, in general, the same as a program, because it can be defined as a finite composition of Scheme’s stan- contain import declarations in places other than the begin- dard arithmetic procedures which does not result in a ning. NaN value.

• obj1 and obj2 are both characters and are the same 6. Standard procedures character according to the char=? procedure (sec- tion 6.6). This chapter describes Scheme’s built-in procedures. The procedures force, promise?, and make-promise are • obj1 and obj2 are both the empty list. intimately associated with the expression types and delay • obj and obj are pairs, vectors, bytevectors, records, , and are described with them in section 4.2.5. 1 2 delay-force or strings that denote the same location in the store In the same way, the procedure is inti- make-parameter (section 3.4). mately associated with the expression type parameterize, and is described with it in section 4.2.6. The eqv? procedure returns #f if: A program may use a global variable definition to bind any variable. It may subsequently alter any such binding by • obj and obj are of different types (section 3.2). an assignment (see section 4.1.6). These operations do not 1 2 modify the behavior of any procedure defined in this report • one of obj1 and obj2 is #t but the other is #f. or imported from a library (see section 5.6). Altering any global binding that has not been introduced by a definition • obj1 and obj2 are symbols but are not the same symbol has an unspecified effect on the behavior of the procedures according to the symbol=? procedure (section 6.5). defined in this chapter. • one of obj1 and obj2 is an exact number but the other When a procedure is said to return a newly allocated object, is an inexact number. it means that the locations in the object are fresh. • obj1 and obj2 are both exact numbers and are numer- ically unequal (in the sense of =). 6.1. Equivalence predicates • obj1 and obj2 are both inexact numbers such that ei- ther they are not both NaN and are numerically un- A predicate is a procedure that always returns a boolean equal (in the sense of =), or they do not yield the value (#t or #f). An equivalence predicate is the compu- same results (in the sense of eqv?) when passed as ar- tational analogue of a mathematical equivalence relation; guments to any other procedure that can be defined as it is symmetric, reflexive, and transitive. Of the equiva- a finite composition of Scheme’s standard arithmetic lence predicates described in this section, eq? is the finest procedures which does not result in a NaN value. or most discriminating, equal? is the coarsest, and eqv? is slightly less discriminating than eq?. • obj1 and obj2 are characters for which the char=? pro- cedure returns #f.

(eqv? obj1 obj2) procedure • one of obj1 and obj2 is the empty list but the other is The eqv? procedure defines a useful equivalence relation on not. objects. Briefly, it returns #t if obj1 and obj2 are normally regarded as the same object. This relation is left slightly • obj1 and obj2 are pairs, vectors, bytevectors, records, open to interpretation, but the following partial specifica- or strings that denote distinct locations. tion of eqv? holds for all implementations of Scheme. • obj1 and obj2 are procedures that would behave dif- The eqv? procedure returns #t if: ferently (return different values or have different side effects) for some arguments. • obj1 and obj2 are both #t or both #f. (eqv? ’a ’a) =⇒ #t • obj1 and obj2 are both symbols and are the same sym- (eqv? ’a ’b) =⇒ #f bol according to the symbol=? procedure (section 6.5). (eqv? 2 2) =⇒ #t (eqv? 2 2.0) =⇒ #f • obj1 and obj2 are both exact numbers and are numer- (eqv? ’() ’()) =⇒ #t ically equal (in the sense of =). (eqv? 100000000 100000000) =⇒ #t 6. Standard procedures 31

(eqv? 0.0 +nan.0) =⇒ #f Since it is an error to modify constant objects (those re- (eqv? (cons 1 2) (cons 1 2))=⇒ #f turned by literal expressions), implementations may share (eqv? (lambda () 1) structure between constants where appropriate. Thus the (lambda () 2)) =⇒ #f value of eqv? on constants is sometimes implementation- (eqv? #f ’nil) =⇒ #f dependent. The following examples illustrate cases in which the above (eqv? ’(a) ’(a)) =⇒ unspecified rules do not fully specify the behavior of eqv?. All that (eqv? "a" "a") =⇒ unspecified can be said about such cases is that the value returned by (eqv? ’(b) (cdr ’(a b))) =⇒ unspecified eqv? must be a boolean. (let ((x ’(a))) (eqv? x x)) =⇒ #t (eqv? "" "") =⇒ unspecified (eqv? ’#() ’#()) =⇒ unspecified Rationale: The above definition of eqv? allows implementa- (eqv? (lambda (x) x) tions latitude in their treatment of procedures and literals: im- (lambda (x) x)) =⇒ unspecified plementations are free either to detect or to fail to detect that (let ((p (lambda (x) x))) two procedures or two literals are equivalent to each other, and (eqv? p p)) =⇒ unspecified can decide whether or not to merge representations of equivalent (eqv? (lambda (x) x) objects by using the same pointer or bit pattern to represent =⇒ unspecified (lambda (y) y)) both. (eqv? 1.0e0 1.0f0) =⇒ unspecified (eqv? +nan.0 +nan.0) =⇒ unspecified Note: If inexact numbers are represented as IEEE binary floating-point numbers, then an implementation of eqv? that Note that (eqv? 0.0 -0.0) will return #f if negative zero simply compares equal-sized inexact numbers for bitwise equal- is distinguished, and #t if negative zero is not distin- ity is correct by the above definition. guished.

The next set of examples shows the use of eqv? with pro- (eq? obj1 obj2) procedure cedures that have local state. The gen-counter procedure The eq? procedure is similar to eqv? except that in some must return a distinct procedure every time, since each cases it is capable of discerning distinctions finer than those procedure has its own internal counter. The gen-loser detectable by eqv?. procedure, however, returns operationally equivalent pro- cedures each time, since the local state does not affect the On symbols, booleans, the empty list, pairs, non-empty value or side effects of the procedures. However, eqv? may strings, vectors, bytevectors, and records, eq? and eqv? are or may not detect this equivalence. guaranteed to have the same behavior. On numbers, char- acters, and procedures, eq?’s behavior is implementation- (define gen-counter dependent, but it will always return either true or false, and (lambda () will return true only when eqv? would also return true. On (let ((n 0)) empty strings, vectors, bytevectors, and records, may (lambda () (set! n (+ n 1)) n)))) eq? (let ((g (gen-counter))) also behave differently from eqv?. (eqv? g g)) =⇒ unspecified (eq? ’a ’a) =⇒ #t (eqv? (gen-counter) (gen-counter)) (eq? ’(a) ’(a)) =⇒ unspecified =⇒ #f (eq? (list ’a) (list ’a)) =⇒ #f (define gen-loser (eq? "a" "a") =⇒ unspecified (lambda () (eq? "" "") =⇒ unspecified (let ((n 0)) (eq? ’() ’()) =⇒ #t (lambda () (set! n (+ n 1)) 27)))) (eq? 2 2) =⇒ unspecified (let ((g (gen-loser))) (eq? #\A #\A) =⇒ unspecified (eqv? g g)) =⇒ unspecified (eq? car car) =⇒ unspecified (eqv? (gen-loser) (gen-loser)) (let ((n (+ 2 3))) =⇒ unspecified (eq? n n)) =⇒ unspecified (let ((x ’(a))) (letrec ((f (lambda () (if (eqv? f g) ’both ’f))) (eq? x x)) =⇒ #t (g (lambda () (if (eqv? f g) ’both ’g)))) (let ((x ’#())) (eqv? f g)) (eq? x x)) =⇒ #t =⇒ unspecified (let ((p (lambda (x) x))) (eq? p p)) =⇒ unspecified (letrec ((f (lambda () (if (eqv? f g) ’f ’both))) (g (lambda () (if (eqv? f g) ’g ’both)))) Rationale: It will usually be possible to implement eq? much (eqv? f g)) more efficiently than eqv?, for example, as a simple pointer com- =⇒ #f parison instead of as some more complicated operation. One 32 Revised7 Scheme reason is that it is not always possible to compute eqv? of two For example, 3 is an integer. Therefore 3 is also a rational, numbers in constant time, whereas eq? implemented as pointer a real, and a complex number. The same is true of the comparison will always finish in constant time. Scheme numbers that model 3. For Scheme numbers, these types are defined by the predicates number?, complex?, real?, rational?, and integer?. (equal? obj obj ) procedure 1 2 There is no simple relationship between a number’s type The equal? procedure, when applied to pairs, vectors, and its representation inside a computer. Although most strings and bytevectors, recursively compares them, return- implementations of Scheme will offer at least two different ing #t when the unfoldings of its arguments into (possibly representations of 3, these different representations denote infinite) trees are equal (in the sense of equal?) as ordered the same integer. trees, and otherwise. It returns the same as when #f eqv? Scheme’s numerical operations treat numbers as abstract applied to booleans, symbols, numbers, characters, ports, data, as independent of their representation as possible. procedures, and the empty list. If two objects are , eqv? Although an implementation of Scheme may use multiple they must be as well. In all other cases, equal? equal? internal representations of numbers, this should not be ap- may return either or . #t #f parent to a casual programmer writing simple programs. Even if its arguments are circular data structures, equal? must always terminate. 6.2.2. Exactness (equal? ’a ’a) =⇒ #t (equal? ’(a) ’(a)) =⇒ #t It is useful to distinguish between numbers that are repre- (equal? ’(a (b) c) sented exactly and those that might not be. For example, ’(a (b) c)) =⇒ #t indexes into data structures must be known exactly, as (equal? "abc" "abc") =⇒ #t must some polynomial coefficients in a symbolic algebra (equal? 2 2) =⇒ #t system. On the other hand, the results of measurements (equal? (make-vector 5 ’a) are inherently inexact, and irrational numbers may be ap- (make-vector 5 ’a)) =⇒ #t proximated by rational and therefore inexact approxima- (equal? ’#1=(a b . #1#) tions. In order to catch uses of inexact numbers where ex- ’#2=(a b a b . #2#))=⇒ #t act numbers are required, Scheme explicitly distinguishes (equal? (lambda (x) x) exact from inexact numbers. This distinction is orthogonal (lambda (y) y)) =⇒ unspecified to the dimension of type. Note: A rule of thumb is that objects are generally equal? if A Scheme number is exact if it was written as an exact con- they print the same. stant or was derived from exact numbers using only exact operations. A number is inexact if it was written as an in- exact constant, if it was derived using inexact ingredients, 6.2. Numbers or if it was derived using inexact operations. Thus inexact- ness is a contagious property of a number. In particular, an exact complex number must have an exact real part and It is important to distinguish between mathematical num- an exact imaginary part; all other complex numbers are bers, the Scheme numbers that attempt to model them, inexact complex numbers. the machine representations used to implement the Scheme numbers, and notations used to write numbers. This report If two implementations produce exact results for a compu- uses the types number, complex, real, rational, and integer tation that did not involve inexact intermediate results, the to refer to both mathematical numbers and Scheme num- two ultimate results will be mathematically equal. This bers. is generally not true of computations involving inexact numbers since approximate methods such as floating-point arithmetic may be used, but it is the duty of each imple- 6.2.1. Numerical types mentation to make the result as close as practical to the mathematically ideal result. Mathematically, numbers are arranged into a tower of sub- types in which each level is a subset of the level above it: Rational operations such as + should always produce ex- act results when given exact arguments. If the operation number is unable to produce an exact result, then it may either complex number report the violation of an implementation restriction or it real number may silently coerce its result to an inexact value. How- rational number ever, (/ 3 4) must not return the mathematically incor- integer rect value 0. See section 6.2.3. 6. Standard procedures 33

Except for exact, the operations described in this section -* must generally return inexact results when given any in- + abs exact arguments. An operation may, however, return an ceiling denominator exact result if it can prove that the value of the result is exact-integer-sqrt expt unaffected by the inexactness of its arguments. For exam- floor floor/ ple, multiplication of any number by an exact zero may floor-quotient floor-remainder gcd lcm produce an exact zero result, even if the other argument is max min inexact. modulo numerator Specifically, the expression (* 0 +inf.0) may return 0, or quotient rationalize +nan.0, or report that inexact numbers are not supported, remainder round or report that non-rational real numbers are not supported, square truncate truncate/ truncate-quotient or fail silently or noisily in other implementation-specific truncate-remainder ways.

It is recommended, but not required, that implementations 6.2.3. Implementation restrictions support exact integers and exact rationals of practically unlimited size and precision, and to implement the above Implementations of Scheme are not required to implement procedures and the / procedure in such a way that they the whole tower of subtypes given in section 6.2.1, but they always return exact results when given exact arguments. If must implement a coherent subset consistent with both one of these procedures is unable to deliver an exact result the purposes of the implementation and the spirit of the when given exact arguments, then it may either report a Scheme language. For example, implementations in which violation of an implementation restriction or it may silently all numbers are real, or in which non-real numbers are al- coerce its result to an inexact number; such a coercion can ways inexact, or in which exact numbers are always integer, cause an error later. Nevertheless, implementations that do are still quite useful. not provide exact rational numbers should return inexact rational numbers rather than reporting an implementation Implementations may also support only a limited range of restriction. numbers of any type, subject to the requirements of this section. The supported range for exact numbers of any An implementation may use floating-point and other ap- type may be different from the supported range for inex- proximate representation strategies for inexact numbers. act numbers of that type. For example, an implementa- This report recommends, but does not require, that imple- tion that uses IEEE binary double-precision floating-point mentations that use floating-point representations follow numbers to represent all its inexact real numbers may also the IEEE 754 standard, and that implementations using support a practically unbounded range of exact integers other representations should match or exceed the preci- and rationals while limiting the range of inexact reals (and sion achievable using these floating-point standards [19]. therefore the range of inexact integers and rationals) to the In particular, the description of transcendental functions dynamic range of the IEEE binary double format. Further- in IEEE 754-2008 should be followed by such implementa- more, the gaps between the representable inexact integers tions, particularly with respect to infinities and NaNs. and rationals are likely to be very large in such an imple- Although Scheme allows a variety of written notations for mentation as the limits of this range are approached. numbers, any particular implementation may support only An implementation of Scheme must support exact in- some of them. For example, an implementation in which tegers throughout the range of numbers permitted as all numbers are real need not support the rectangular and indexes of lists, vectors, bytevectors, and strings or polar notations for complex numbers. If an implementa- that result from computing the length of one of these. tion encounters an exact numerical constant that it cannot The length, vector-length, bytevector-length, and represent as an exact number, then it may either report a string-length procedures must return an exact integer, violation of an implementation restriction or it may silently and it is an error to use anything but an exact integer as represent the constant by an inexact number. an index. Furthermore, any integer constant within the index range, if expressed by an exact integer syntax, must 6.2.4. Implementation extensions be read as an exact integer, regardless of any implemen- tation restrictions that apply outside this range. Finally, Implementations may provide more than one representa- the procedures listed below will always return exact inte- tion of floating-point numbers with differing precisions. In ger results provided all their arguments are exact integers an implementation which does so, an inexact result must and the mathematically expected results are representable be represented with at least as much precision as is used as exact integers within the implementation: to express any of the inexact arguments to that operation. 34 Revised7 Scheme

Although it is desirable for potentially inexact operations negative zeros is negative, and the result of subtracting such as sqrt to produce exact answers when applied to (positive) zero from a negative zero is likewise negative. exact arguments, if an exact number is operated upon so However, numerical comparisons treat negative zero as as to produce an inexact result, then the most precise rep- equal to zero. resentation available must be used. For example, the value Note that both the real and the imaginary parts of a com- of (sqrt 4) should be 2, but in an implementation that plex number can be infinities, NaNs, or negative zero. provides both single and double precision floating point numbers it may be the latter but must not be the former. 6.2.5. Syntax of numerical constants It is the programmer’s responsibility to avoid using inexact number objects with magnitude or significand too large to The syntax of the written representations for numbers is be represented in the implementation. described formally in section 7.1.1. Note that case is not In addition, implementations may distinguish special num- significant in numerical constants. bers called positive infinity, negative infinity, NaN, and A number can be written in binary, octal, decimal, or hexa- negative zero. decimal by the use of a radix prefix. The radix prefixes are #b (binary), #o (octal), #d (decimal), and #x (hexa- Positive infinity is regarded as an inexact real (but not decimal). With no radix prefix, a number is assumed to be rational) number that represents an indeterminate value expressed in decimal. greater than the numbers represented by all rational num- bers. Negative infinity is regarded as an inexact real A numerical constant can be specified to be either exact or (but not rational) number that represents an indetermi- inexact by a prefix. The prefixes are #e for exact, and #i nate value less than the numbers represented by all rational for inexact. An exactness prefix may appear before or after numbers. any radix prefix that is used. If the written representation of a number has no exactness prefix, the constant is inexact Adding or multiplying an infinite value by any finite real if it contains a decimal point or an exponent. Otherwise, value results in an appropriately signed infinity; however, it is exact. the sum of positive and negative infinities is a NaN. Posi- tive infinity is the reciprocal of zero, and negative infinity is In systems with inexact numbers of varying precisions it the reciprocal of negative zero. The behavior of the tran- can be useful to specify the precision of a constant. For scendental functions is sensitive to infinity in accordance this purpose, implementations may accept numerical con- with IEEE 754. stants written with an exponent marker that indicates the desired precision of the inexact representation. The letter A NaN is regarded as an inexact real (but not rational) s, f, d, or l, meaning short, single, double, or long preci- number so indeterminate that it might represent any real sion, respectively, may be used in place of e. The default value, including positive or negative infinity, and might precision has at least as much precision as double, but im- even be greater than positive infinity or less than negative plementations may allow this default to be set by the user. infinity. An implementation that does not support non- real numbers may use NaN to represent non-real values 3.14159265358979F0 like (sqrt -1.0) and (asin 2.0). Round to single — 3.141593 0.6L0 A NaN always compares false to any number, including a Extend to long — .600000000000000 NaN. An arithmetic operation where one operand is NaN The numbers positive infinity, negative infinity, and NaN returns NaN, unless the implementation can prove that the are written +inf.0, -inf.0 and +nan.0 respectively. NaN result would be the same if the NaN were replaced by any may also be written -nan.0. The use of signs in the written rational number. Dividing zero by zero results in NaN representation does not necessarily reflect the underlying unless both zeros are exact. sign of the NaN value, if any. Implementations are not re- Negative zero is an inexact real value written -0.0 and is quired to support these numbers, but if they do, they must distinct (in the sense of eqv?) from 0.0. A Scheme im- do so in general conformance with IEEE 754. However, im- plementation is not required to distinguish negative zero. plementations are not required to support signaling NaNs, If it does, however, the behavior of the transcendental nor to provide a way to distinguish between different NaNs. functions is sensitive to the distinction in accordance with There are two notations provided for non-real complex IEEE 754. Specifically, in a Scheme implementing both numbers: the rectangular notation a+bi, where a is the complex numbers and negative zero, the branch cut of the real part and b is the imaginary part; and the polar no- complex logarithm function is such that (imag-part (log tation r@θ, where r is the magnitude and θ is the phase is −π rather than π. -1.0-0.0i)) (angle) in radians. These are related by the equation Furthermore, the negation of negative zero is ordinary zero a + bi = r cos θ + (r sin θ)i. All of a, b, r, and θ are real and vice versa. This implies that the sum of two or more numbers. 6. Standard procedures 35

6.2.6. Numerical operations (exact? z) procedure (inexact? z) procedure The reader is referred to section 1.3.3 for a summary of These numerical predicates provide tests for the exactness the naming conventions used to specify restrictions on the of a quantity. For any Scheme number, precisely one of types of arguments to numerical routines. The examples these predicates is true. used in this section assume that any numerical constant written using an exact notation is indeed represented as (exact? 3.0) =⇒ #f an exact number. Some examples also assume that cer- (exact? #e3.0) =⇒ #t tain numerical constants written using an inexact notation (inexact? 3.) =⇒ #t can be represented without loss of accuracy; the inexact constants were chosen so that this is likely to be true in implementations that use IEEE binary doubles to repre- (exact-integer? z) procedure sent inexact numbers. Returns #t if z is both exact and an integer; otherwise returns #f.

(number? obj ) procedure (exact-integer? 32) =⇒ #t (complex? obj ) procedure (exact-integer? 32.0) =⇒ #f (real? obj ) procedure (exact-integer? 32/5) =⇒ #f (rational? obj ) procedure (integer? obj ) procedure (finite? z) inexact library procedure These numerical type predicates can be applied to any kind of argument, including non-numbers. They return #t if the The finite? procedure returns #t on all real numbers ex- object is of the named type, and otherwise they return #f. cept +inf.0, -inf.0, and +nan.0, and on complex num- In general, if a type predicate is true of a number then bers if their real and imaginary parts are both finite. Oth- all higher type predicates are also true of that number. erwise it returns #f. Consequently, if a type predicate is false of a number, then (finite? 3) =⇒ #t all lower type predicates are also false of that number. (finite? +inf.0) =⇒ #f (finite? 3.0+inf.0i) =⇒ #f If z is a complex number, then (real? z) is true if and only if (zero? (imag-part z)) is true. If x is an inexact real number, then (integer? x) is true if and only if (= (infinite? z) inexact library procedure x (round x)). The infinite? procedure returns #t on the real numbers The numbers +inf.0, -inf.0, and +nan.0 are real but not +inf.0 and -inf.0, and on complex numbers if their real rational. or imaginary parts or both are infinite. Otherwise it re- turns #f. (complex? 3+4i) =⇒ #t (complex? 3) =⇒ #t (infinite? 3) =⇒ #f (real? 3) =⇒ #t (infinite? +inf.0) =⇒ #t (real? -2.5+0i) =⇒ #t (infinite? +nan.0) =⇒ #f (real? -2.5+0.0i) =⇒ #f (infinite? 3.0+inf.0i) =⇒ #t (real? #e1e10) =⇒ #t (real? +inf.0) =⇒ #t (real? +nan.0) =⇒ #t (nan? z) inexact library procedure (rational? -inf.0) =⇒ #f (rational? 6/10) =⇒ #t The nan? procedure returns #t on +nan.0, and on complex (rational? 6/3) =⇒ #t numbers if their real or imaginary parts or both are +nan.0. (integer? 3+0i) =⇒ #t Otherwise it returns #f. (integer? 3.0) =⇒ #t (integer? 8/4) =⇒ #t (nan? +nan.0) =⇒ #t (nan? 32) =⇒ #f Note: The behavior of these type predicates on inexact num- (nan? +nan.0+5.0i) =⇒ #t bers is unreliable, since any inaccuracy might affect the result. (nan? 1+2i) =⇒ #f

Note: In many implementations the complex? procedure will be the same as number?, but unusual implementations may rep- (= z1 z2 z3 ... ) procedure resent some irrational numbers exactly or may extend the num- (< x1 x2 x3 ... ) procedure ber system to support some kind of non-complex numbers. (> x1 x2 x3 ... ) procedure 36 Revised7 Scheme

(<= x1 x2 x3 ... ) procedure (+ 3 4) =⇒ 7 (>= x1 x2 x3 ... ) procedure (+ 3) =⇒ 3 (+) =⇒ 0 These procedures return #t if their arguments are (respec- (* 4) =⇒ 4 tively): equal, monotonically increasing, monotonically de- (*) =⇒ 1 creasing, monotonically non-decreasing, or monotonically non-increasing, and #f otherwise. If any of the arguments are +nan.0, all the predicates return #f. They do not dis- (- z) procedure tinguish between inexact zero and inexact negative zero. (- z1 z2 ... ) procedure (/ z) procedure These predicates are required to be transitive. (/ z1 z2 ... ) procedure Note: The implementation approach of converting all argu- With two or more arguments, these procedures return the ments to inexact numbers if any argument is inexact is not difference or quotient of their arguments, associating to the transitive. For example, let big be (expt 2 1000), and assume left. With one argument, however, they return the additive that big is exact and that inexact numbers are represented by or multiplicative inverse of their argument. 64-bit IEEE binary floating point numbers. Then (= (- big 1) (inexact big)) and (= (inexact big) (+ big 1)) would It is an error if any argument of / other than the first is both be true with this approach, because of the limitations of an exact zero. If the first argument is an exact zero, an IEEE representations of large integers, whereas (= (- big 1) implementation may return an exact zero unless one of the (+ big 1)) is false. Converting inexact values to exact num- other arguments is a NaN. bers that are the same (in the sense of =) to them will avoid this (- 3 4) =⇒ -1 problem, though special care must be taken with infinities. (- 3 4 5) =⇒ -6 Note: While it is not an error to compare inexact numbers (- 3) =⇒ -3 (/ 3 4 5) =⇒ 3/20 using these predicates, the results are unreliable because a small (/ 3) =⇒ 1/3 inaccuracy can affect the result; this is especially true of = and zero?. When in doubt, consult a numerical analyst. (abs x) procedure (zero? z) procedure The abs procedure returns the absolute value of its argu- (positive? x) procedure ment. (negative? x) procedure (abs -7) =⇒ 7 (odd? n) procedure (even? n) procedure (floor/ n1 n2) procedure These numerical predicates test a number for a particular (floor-quotient n1 n2) procedure property, returning #t or #f. See note above. (floor-remainder n1 n2) procedure (truncate/ n1 n2) procedure (max x1 x2 ... ) procedure (truncate-quotient n1 n2) procedure (min x1 x2 ... ) procedure (truncate-remainder n1 n2) procedure These procedures return the maximum or minimum of their These procedures implement number-theoretic (integer) di- arguments. vision. It is an error if n2 is zero. The procedures ending in return two integers; the other procedures return an (max 3 4) =⇒ 4 ; exact / (max 3.9 4) =⇒ 4.0 ; inexact integer. All the procedures compute a quotient nq and re- mainder nr such that n1 = n2nq + nr. For each of the Note: If any argument is inexact, then the result will also be division operators, there are three procedures defined as inexact (unless the procedure can prove that the inaccuracy is follows: not large enough to affect the result, which is possible only in unusual implementations). If min or max is used to compare (hoperatori/ n1 n2) =⇒ nq nr (hoperatori-quotient n n ) =⇒ n numbers of mixed exactness, and the numerical value of the 1 2 q (hoperatori-remainder n n ) =⇒ n result cannot be represented as an inexact number without loss 1 2 r of accuracy, then the procedure may report a violation of an The remainder nr is determined by the choice of integer implementation restriction. nq: nr = n1 − n2nq. Each set of operators uses a different choice of nq:

(+ z1 ... ) procedure floor nq = bn1/n2c (* z1 ... ) procedure truncate nq = truncate(n1/n2)

These procedures return the sum or product of their argu- For any of the operators, and for integers n1 and n2 with ments. n2 not equal to 0, 6. Standard procedures 37

(= n1 (+ (* n2 (hoperatori-quotient n1 n2)) (round x) procedure (hoperatori-remainder n1 n2))) =⇒ #t These procedures return integers. The floor procedure provided all numbers involved in that computation are ex- returns the largest integer not larger than x. The ceiling act. procedure returns the smallest integer not smaller than x, Examples: truncate returns the integer closest to x whose absolute value is not larger than the absolute value of x, and round (floor/ 5 2) =⇒ 2 1 returns the closest integer to x, rounding to even when x (floor/ -5 2) =⇒ -3 1 is halfway between two integers. (floor/ 5 -2) =⇒ -3 -1 (floor/ -5 -2) =⇒ 2 -1 Rationale: The round procedure rounds to even for consistency (truncate/ 5 2) =⇒ 2 1 with the default rounding mode specified by the IEEE 754 IEEE (truncate/ -5 2) =⇒ -2 -1 floating-point standard. (truncate/ 5 -2) =⇒ -2 1 (truncate/ -5 -2) =⇒ 2 -1 Note: If the argument to one of these procedures is inexact, (truncate/ -5.0 -2) =⇒ 2.0 -1.0 then the result will also be inexact. If an exact value is needed, the result can be passed to the exact procedure. If the argu- ment is infinite or a NaN, then it is returned. (quotient n1 n2) procedure (floor -4.3) =⇒ -5.0 (remainder n1 n2) procedure (modulo n n ) procedure (ceiling -4.3) =⇒ -4.0 1 2 (truncate -4.3) =⇒ -4.0 The quotient and remainder procedures are equivalent (round -4.3) =⇒ -4.0 to truncate-quotient and truncate-remainder, respec- tively, and modulo is equivalent to floor-remainder. (floor 3.5) =⇒ 3.0 (ceiling 3.5) =⇒ 4.0 Note: These procedures are provided for backward compati- (truncate 3.5) =⇒ 3.0 bility with earlier versions of this report. (round 3.5) =⇒ 4.0 ; inexact

(round 7/2) =⇒ 4 ; exact (gcd n ... ) procedure 1 (round 7) =⇒ 7 (lcm n1 ... ) procedure These procedures return the greatest common divisor or least common multiple of their arguments. The result is (rationalize x y) procedure always non-negative.

(gcd 32 -36) =⇒ 4 The rationalize procedure returns the simplest rational (gcd) =⇒ 0 number differing from x by no more than y. A rational (lcm 32 -36) =⇒ 288 number r1 is simpler than another rational number r2 if (lcm 32.0 -36) =⇒ 288.0 ; inexact r1 = p1/q1 and r2 = p2/q2 (in lowest terms) and |p1| ≤ |p2| (lcm) =⇒ 1 and |q1| ≤ |q2|. Thus 3/5 is simpler than 4/7. Although not all rationals are comparable in this ordering (consider 2/7 and 3/5), any interval contains a rational number that is (numerator q) procedure simpler than every other rational number in that interval (denominator q) procedure (the simpler 2/5 lies between 2/7 and 3/5). Note that These procedures return the numerator or denominator of 0 = 0/1 is the simplest rational of all. their argument; the result is computed as if the argument was represented as a fraction in lowest terms. The denom- (rationalize inator is always positive. The denominator of 0 is defined (exact .3) 1/10) =⇒ 1/3 ; exact to be 1. (rationalize .3 1/10) =⇒ #i1/3 ; inexact (numerator (/ 6 4)) =⇒ 3 (denominator (/ 6 4)) =⇒ 2 (exp z) inexact library procedure (denominator (log z) inexact library procedure (inexact (/ 6 4))) =⇒ 2.0 (log z1 z2) inexact library procedure (sin z) inexact library procedure (floor x) procedure (cos z) inexact library procedure (ceiling x) procedure (tan z) inexact library procedure (truncate x) procedure (asin z) inexact library procedure 38 Revised7 Scheme

(acos z) inexact library procedure The above specification follows [35], which in turn (atan z) inexact library procedure cites [27]; refer to these sources for more detailed discussion (atan y x) inexact library procedure of branch cuts, boundary conditions, and implementation of these functions. When it is possible, these procedures These procedures compute the usual transcendental func- produce a real result from a real argument. tions. The log procedure computes the natural logarithm of z (not the base ten logarithm) if a single argument is given, or the base-z2 logarithm of z1 if two arguments are (square z) procedure given. The asin, acos, and atan procedures compute arc- Returns the square of z. This is equivalent to (* z z). sine (sin−1), arc-cosine (cos−1), and arctangent (tan−1), (square 42) =⇒ 1764 respectively. The two-argument variant of atan computes (square 2.0) =⇒ 4.0 (angle (make-rectangular x y)) (see below), even in implementations that don’t support complex numbers. (sqrt z) inexact library procedure In general, the mathematical functions log, arcsine, arc- cosine, and arctangent are multiply defined. The value of Returns the principal square root of z. The result will log z is defined to be the one whose imaginary part lies have either a positive real part, or a zero real part and a in the range from −π (inclusive if -0.0 is distinguished, non-negative imaginary part. exclusive otherwise) to π (inclusive). The value of log 0 is (sqrt 9) =⇒ 3 mathematically undefined. With log defined this way, the (sqrt -1) =⇒ +i values of sin−1 z, cos−1 z, and tan−1 z are according to the following formulæ: (exact-integer-sqrt k) procedure p sin−1 z = −i log(iz + 1 − z2) Returns two non-negative exact integers s and r where k = s2 + r and k < (s + 1)2. cos−1 z = π/2 − sin−1 z (exact-integer-sqrt 4) =⇒ 2 0 tan−1 z = (log(1 + iz) − log(1 − iz))/(2i) (exact-integer-sqrt 5) =⇒ 2 1

However, (log 0.0) returns -inf.0 (and (log -0.0) re- (expt z1 z2) procedure turns π ) if the implementation supports infinities -inf.0+ i Returns z raised to the power z . For nonzero z , this is (and -0.0). 1 2 1

z2 z2 log z1 The range of (atan y x) is as in the following table. The z1 = e asterisk (*) indicates that the entry applies to implemen- The value of 0z is 1 if (zero? z), 0 if (real-part z) is tations that distinguish minus zero. positive, and an error otherwise. Similarly for 0.0z, with y condition x condition range of result r inexact results. y = 0.0 x > 0.0 0.0

∗ y = +0.0 x > 0.0 +0.0 (make-rectangular x1 x2) complex library procedure ∗ y = −0.0 x > 0.0 −0.0 (make-polar x3 x4) complex library procedure π y > 0.0 x > 0.0 0.0 < r < 2 (real-part z) complex library procedure π y > 0.0 x = 0.0 2 (imag-part z) complex library procedure π y > 0.0 x < 0.0 2 < r < π (magnitude z) complex library procedure y = 0.0 x < 0 π (angle z) complex library procedure ∗ y = +0.0 x < 0.0 π Let x , x , x , and x be real numbers and z be a complex ∗ y = −0.0 x < 0.0 −π 1 2 3 4 π number such that y < 0.0 x < 0.0 −π < r < − 2 π ix y < 0.0 x = 0.0 − 2 z = x + x i = x · e 4 π 1 2 3 y < 0.0 x > 0.0 − 2 < r < 0.0 y = 0.0 x = 0.0 undefined Then all of ∗ y = +0.0 x = +0.0 +0.0 (make-rectangular x1 x2) =⇒ z ∗ y = −0.0 x = +0.0 −0.0 (make-polar x3 x4) =⇒ z ∗ y = +0.0 x = −0.0 π (real-part z) =⇒ x1 ∗ y = −0.0 x = −0.0 −π (imag-part z) =⇒ x2 π ∗ y = +0.0 x = 0 2 (magnitude z) =⇒ |x3| π (angle z) =⇒ x ∗ y = −0.0 x = 0 − 2 angle 6. Standard procedures 39 are true, where −π ≤ xangle ≤ π with xangle = x4 + 2πn The procedure number->string takes a number and a for some integer n. radix and returns as a string an external representation of the given number in the given radix such that The make-polar procedure may return an inexact complex number even if its arguments are exact. The real-part (let ((number number) and imag-part procedures may return exact real numbers (radix radix)) when applied to an inexact complex number if the corre- (eqv? number (string->number (number->string number sponding argument passed to make-rectangular was ex- radix) act. radix))) Rationale: The magnitude procedure is the same as abs for a is true. It is an error if no possible result makes this ex- real argument, but abs is in the base library, whereas magnitude pression true. If omitted, radix defaults to 10. is in the optional complex library. If z is inexact, the radix is 10, and the above expression can be satisfied by a result that contains a decimal point, (inexact z) procedure then the result contains a decimal point and is expressed (exact z) procedure using the minimum number of digits (exclusive of exponent The procedure inexact returns an inexact representation and trailing zeroes) needed to make the above expression of z. The value returned is the inexact number that is nu- true [7, 9]; otherwise the format of the result is unspecified. merically closest to the argument. For inexact arguments, The result returned by number->string never contains an the result is the same as the argument. For exact complex explicit radix prefix. numbers, the result is a complex number whose real and imaginary parts are the result of applying inexact to the Note: The error case can occur only when z is not a complex real and imaginary parts of the argument, respectively. If number or is a complex number with a non-rational real or an exact argument has no reasonably close inexact equiv- imaginary part. alent (in the sense of =), then a violation of an implemen- Rationale: If z is an inexact number and the radix is 10, then tation restriction may be reported. the above expression is normally satisfied by a result containing The procedure exact returns an exact representation of a decimal point. The unspecified case allows for infinities, NaNs, z. The value returned is the exact number that is nu- and unusual representations. merically closest to the argument. For exact arguments, the result is the same as the argument. For inexact non- (string->number string) procedure integral real arguments, the implementation may return a (string->number string radix) procedure rational approximation, or may report an implementation Returns a number of the maximally precise representation violation. For inexact complex arguments, the result is a expressed by the given string. It is an error if radix is not complex number whose real and imaginary parts are the 2, 8, 10, or 16. result of applying exact to the real and imaginary parts of the argument, respectively. If an inexact argument has If supplied, radix is a default radix that will be overrid- no reasonably close exact equivalent, (in the sense of =), den if an explicit radix prefix is present in string (e.g. then a violation of an implementation restriction may be "#o177"). If radix is not supplied, then the default radix reported. is 10. If string is not a syntactically valid notation for a number, or would result in a number that the implemen- These procedures implement the natural one-to-one corre- tation cannot represent, then string->number returns #f. spondence between exact and inexact integers throughout An error is never signaled due to the content of string. an implementation-dependent range. See section 6.2.3. (string->number "100") =⇒ 100 Note: These procedures were known in R5RS as (string->number "100" 16) =⇒ 256 exact->inexact and inexact->exact, respectively, but they (string->number "1e2") =⇒ 100.0 have always accepted arguments of any exactness. The new names are clearer and shorter, as well as being compatible with Note: The domain of string->number may be restricted by im- R6RS. plementations in the following ways. If all numbers supported by an implementation are real, then string->number is permit- ted to return #f whenever string uses the polar or rectangular 6.2.7. Numerical input and output notations for complex numbers. If all numbers are integers, then string->number may return #f whenever the fractional nota- tion is used. If all numbers are exact, then string->number (number->string z) procedure may return #f whenever an exponent marker or explicit exact- ness prefix is used. If all inexact numbers are integers, then (number->string z radix) procedure string->number may return #f whenever a decimal point is It is an error if radix is not one of 2, 8, 10, or 16. used. 40 Revised7 Scheme

The rules used by a particular implementation for 6.4. Pairs and lists string->number must also be applied to read and to the routine that reads programs, in order to maintain consistency A pair (sometimes called a dotted pair) is a record structure between internal numeric processing, I/O, and the processing with two fields called the car and cdr fields (for historical of programs. As a consequence, the R5RS permission to reasons). Pairs are created by the procedure cons. The return #f when string has an explicit radix prefix has been car and cdr fields are accessed by the procedures car and withdrawn. cdr. The car and cdr fields are assigned by the procedures set-car! and set-cdr!. 6.3. Booleans Pairs are used primarily to represent lists. A list can be defined recursively as either the empty list or a pair whose The standard boolean objects for true and false are writ- cdr is a list. More precisely, the set of lists is defined as ten as #t and #f. Alternatively, they may be written the smallest set X such that #true and #false, respectively. What really matters, though, are the objects that the Scheme conditional expres- • The empty list is in X . sions (if, cond, and, or, when, unless, do) treat as true or false. The phrase “a true value” (or sometimes just “true”) • If list is in X , then any pair whose cdr field contains means any object treated as true by the conditional expres- list is also in X . sions, and the phrase “a false value” (or “false”) means any object treated as false by the conditional expressions. The objects in the car fields of successive pairs of a list are Of all the Scheme values, only #f counts as false in condi- the elements of the list. For example, a two-element list tional expressions. All other Scheme values, including #t, is a pair whose car is the first element and whose cdr is a count as true. pair whose car is the second element and whose cdr is the Note: Unlike some other dialects of Lisp, Scheme distinguishes empty list. The length of a list is the number of elements, #f and the empty list from each other and from the symbol which is the same as the number of pairs. nil. The empty list is a special object of its own type. It is not Boolean constants evaluate to themselves, so they do not a pair, it has no elements, and its length is zero. need to be quoted in programs. Note: The above definitions imply that all lists have finite #t =⇒ #t length and are terminated by the empty list. #f =⇒ #f The most general notation (external representation) for ’#f =⇒ #f Scheme pairs is the “dotted” notation (c1 . c2) where c1 is the value of the car field and c2 is the value of the cdr (not obj ) procedure field. For example (4 . 5) is a pair whose car is 4 and The not procedure returns #t if obj is false, and returns whose cdr is 5. Note that (4 . 5) is the external repre- #f otherwise. sentation of a pair, not an expression that evaluates to a pair. (not #t) =⇒ #f (not 3) =⇒ #f A more streamlined notation can be used for lists: the (not (list 3)) =⇒ #f elements of the list are simply enclosed in parentheses and (not #f) =⇒ #t separated by spaces. The empty list is written () . For (not ’()) =⇒ #f example, (not (list)) =⇒ #f (not ’nil) =⇒ #f (a b c d e) and (boolean? obj ) procedure (a . (b . (c . (d . (e . ()))))) The boolean? predicate returns #t if obj is either #t or #f and returns #f otherwise. are equivalent notations for a list of symbols. (boolean? #f) =⇒ #t A chain of pairs not ending in the empty list is called an (boolean? 0) =⇒ #f improper list. Note that an improper list is not a list. (boolean? ’()) =⇒ #f The list and dotted notations can be combined to represent improper lists: (boolean=? boolean boolean boolean ... ) procedure 1 2 3 (a b c . d) Returns #t if all the arguments are booleans and all are #t or all are #f. is equivalent to 6. Standard procedures 41

(a . (b . (c . d))) (car ’(a b c)) =⇒ a (car ’((a) b c d)) =⇒ (a) Whether a given pair is a list depends upon what is stored (car ’(1 . 2)) =⇒ 1 in the cdr field. When the set-cdr! procedure is used, an (car ’()) =⇒ error object can be a list one moment and not the next: (cdr pair) procedure (define x (list ’a ’b ’c)) (define y x) Returns the contents of the cdr field of pair. Note that it y =⇒ (a b c) is an error to take the cdr of the empty list. (list? y) =⇒ #t (cdr ’((a) b c d)) =⇒ (b c d) (set-cdr! x 4) =⇒ unspecified (cdr ’(1 . 2)) =⇒ 2 x =⇒ (a . 4) (cdr ’()) =⇒ error (eqv? x y) =⇒ #t y =⇒ (a . 4) (list? y) =⇒ #f (set-car! pair obj ) procedure (set-cdr! x x) =⇒ unspecified Stores obj in the car field of pair. (list? x) =⇒ #f (define (f) (list ’not-a-constant-list)) (define (g) ’(constant-list)) Within literal expressions and representations of ob- (set-car! (f) 3) =⇒ unspecified jects read by the read procedure, the forms ’hdatumi, (set-car! (g) 3) =⇒ error `hdatumi, ,hdatumi, and ,@hdatumi denote two-ele- ment lists whose first elements are the symbols quote, (set-cdr! pair obj ) procedure quasiquote, unquote, and unquote-splicing, respec- Stores obj in the cdr field of pair. tively. The second element in each case is hdatumi. This convention is supported so that arbitrary Scheme programs pair procedure can be represented as lists. That is, according to Scheme’s (caar ) pair procedure grammar, every hexpressioni is also a hdatumi (see sec- (cadr ) pair procedure tion 7.1.2). Among other things, this permits the use of (cdar ) (cddr pair) procedure the read procedure to parse Scheme programs. See sec- tion 3.3. These procedures are compositions of car and cdr as fol- lows: (define (caar x) (car (car x))) (pair? obj ) procedure (define (cadr x) (car (cdr x))) The pair? predicate returns #t if obj is a pair, and other- (define (cdar x) (cdr (car x))) wise returns #f. (define (cddr x) (cdr (cdr x))) (define (caar x) (car (car x))) (pair? ’(a . b)) =⇒ #t (pair? ’(a b c)) =⇒ #t (caaar pair) cxr library procedure (pair? ’()) =⇒ #f (caadr pair) cxr library procedure (pair? ’#(a b)) =⇒ #f . . . . (cdddar pair) cxr library procedure

(cons obj1 obj2) procedure (cddddr pair) cxr library procedure These twenty-four procedures are further compositions of Returns a newly allocated pair whose car is obj1 and whose cdr is obj . The pair is guaranteed to be different (in the car and cdr on the same principles. For example, caddr 2 could be defined by sense of eqv?) from every existing object. (define caddr (lambda (x) (car (cdr (cdr x))))). (cons ’a ’()) =⇒ (a) (cons ’(a) ’(b c d)) =⇒ ((a) b c d) Arbitrary compositions up to four deep are provided. (cons "a" ’(b c)) =⇒ ("a" b c) (cons ’a 3) =⇒ (a . 3) (null? obj ) procedure (cons ’(a b) ’c) =⇒ ((a b) . c) Returns #t if obj is the empty list, otherwise returns #f.

(list? obj ) procedure (car pair) procedure Returns #t if obj is a list. Otherwise, it returns #f. By Returns the contents of the car field of pair. Note that it definition, all lists have finite length and are terminated by is an error to take the car of the empty list. the empty list. 42 Revised7 Scheme

(list? ’(a b c)) =⇒ #t (list-tail list k) procedure (list? ’()) =⇒ #t It is an error if list has fewer than k elements. (list? ’(a . b)) =⇒ #f (let ((x (list ’a))) Returns the sublist of list obtained by omitting the first k (set-cdr! x x) elements. The list-tail procedure could be defined by (list? x)) =⇒ #f (define list-tail (lambda (x k) (if (zero? k) (make-list k) procedure x (make-list k fill) procedure (list-tail (cdr x) (- k 1))))) Returns a newly allocated list of k elements. If a second argument is given, then each element is initialized to fill. (list-ref list k) procedure Otherwise the initial contents of each element is unspeci- The list argument may be circular, but it is an error if list has fied. fewer than k elements. (make-list 2 3) =⇒ (3 3) Returns the kth element of list. (This is the same as the car of (list-tail list k).) (list-ref ’(a b c d) 2) =⇒ c (list obj ... ) procedure (list-ref ’(a b c d) Returns a newly allocated list of its arguments. (exact (round 1.8))) =⇒ c (list ’a (+ 3 4) ’c) =⇒ (a 7 c) (list) =⇒ () (list-set! list k obj ) procedure It is an error if k is not a valid index of list. (length list) procedure The list-set! procedure stores obj in element k of Returns the length of list. list. (let ((ls (list ’one ’two ’five!))) (length ’(a b c)) =⇒ 3 (list-set! ls 2 ’three) (length ’(a (b) (c d e))) =⇒ 3 ls) (length ’()) =⇒ 0 =⇒ (one two three)

(list-set! ’(0 1 2) 1 "oops") list ... procedure (append ) =⇒ error ; constant list The last argument, if there is one, may be of any type. obj list procedure Returns a list consisting of the elements of the first list (memq ) obj list procedure followed by the elements of the other lists. If there are no (memv ) obj list procedure arguments, the empty list is returned. If there is exactly (member ) obj list compare procedure one argument, it is returned. Otherwise the resulting list (member ) is always newly allocated, except that it shares structure These procedures return the first sublist of list whose car with the last argument. An improper list results if the last is obj , where the sublists of list are the non-empty lists argument is not a proper list. returned by (list-tail list k) for k less than the length of list. If obj does not occur in list, then #f (not the empty (append ’(x) ’(y)) =⇒ (x y) list) is returned. The memq procedure uses eq? to compare =⇒ (append ’(a) ’(b c d)) (a b c d) obj with the elements of list, while memv uses eqv? and (append ’(a (b)) ’((c))) =⇒ (a (b) (c)) member uses compare, if given, and equal? otherwise. (append ’(a b) ’(c . d)) =⇒ (a b c . d) (memq ’a ’(a b c)) =⇒ (a b c) (append ’() ’a) =⇒ a (memq ’b ’(a b c)) =⇒ (b c) (memq ’a ’(b c d)) =⇒ #f (memq (list ’a) ’(b (a) c)) =⇒ #f (reverse list) procedure (member (list ’a) Returns a newly allocated list consisting of the elements of ’(b (a) c)) =⇒ ((a) c) list in reverse order. (member "B" ’("a" "b" "c") (reverse ’(a b c)) =⇒ (c b a) string-ci=?) =⇒ ("b" "c") (reverse ’(a (b c) d (e (f)))) (memq 101 ’(100 101 102)) =⇒ unspecified =⇒ ((e (f)) d (b c) a) (memv 101 ’(100 101 102)) =⇒ (101 102) 6. Standard procedures 43

(assq obj alist) procedure The rules for writing a symbol are exactly the same as the (assv obj alist) procedure rules for writing an identifier; see sections 2.1 and 7.1.1. (assoc obj alist) procedure It is guaranteed that any symbol that has been returned obj alist compare procedure (assoc ) as part of a literal expression, or read using the read pro- It is an error if alist (for “association list”) is not a list of pairs. cedure, and subsequently written out using the write pro- cedure, will read back in as the identical symbol (in the These procedures find the first pair in alist whose car field sense of eqv?). is obj , and returns that pair. If no pair in alist has obj as its car, then #f (not the empty list) is returned. The Note: Some implementations have values known as “unin- assq procedure uses eq? to compare obj with the car fields terned symbols,” which defeat write/read invariance, and also of the pairs in alist, while assv uses eqv? and assoc uses violate the rule that two symbols are the same if and only if compare if given and equal? otherwise. their names are spelled the same. This report does not specify the behavior of implementation-dependent extensions. (define e ’((a 1) (b 2) (c 3))) (assq ’a e) =⇒ (a 1) (assq ’b e) =⇒ (b 2) (symbol? obj ) procedure (assq ’d e) =⇒ #f Returns #t if obj is a symbol, otherwise returns #f. (assq (list ’a) ’(((a)) ((b)) ((c)))) =⇒ #f (symbol? ’foo) =⇒ #t (assoc (list ’a) ’(((a)) ((b)) ((c)))) (symbol? (car ’(a b))) =⇒ #t =⇒ ((a)) (symbol? "bar") =⇒ #f (assoc 2.0 ’((1 1) (2 4) (3 9)) =) (symbol? ’nil) =⇒ #t =⇒ (2 4) (symbol? ’()) =⇒ #f (assq 5 ’((2 3) (5 7) (11 13))) (symbol? #f) =⇒ #f =⇒ unspecified (assv 5 ’((2 3) (5 7) (11 13))) =⇒ (5 7) (symbol=? symbol1 symbol2 symbol3 ... ) procedure

Rationale: Although they are often used as predicates, memq, Returns #t if all the arguments are symbols and all have memv, member, assq, assv, and assoc do not have question the same names in the sense of string=?. marks in their names because they return potentially useful Note: The definition above assumes that none of the arguments values rather than just #t or #f. are uninterned symbols.

(list-copy obj ) procedure (symbol->string symbol) procedure Returns a newly allocated copy of the given obj if it is a Returns the name of symbol as a string, but without adding list. Only the pairs themselves are copied; the cars of the escapes. It is an error to apply mutation procedures like result are the same (in the sense of eqv?) as the cars of list. string-set! to strings returned by this procedure. If obj is an improper list, so is the result, and the final cdrs (symbol->string ’flying-fish) are the same in the sense of eqv?. An obj which is not a =⇒ "flying-fish" list is returned unchanged. It is an error if obj is a circular (symbol->string ’Martin) =⇒ "Martin" list. (symbol->string (string->symbol "Malvina")) (define a ’(1 8 2 8)) ; a may be immutable =⇒ "Malvina" (define b (list-copy a)) (set-car! b 3) ; b is mutable b =⇒ (3 8 2 8) (string->symbol string) procedure a =⇒ (1 8 2 8) Returns the symbol whose name is string. This procedure can create symbols with names containing special charac- ters that would require escaping when written, but does 6.5. Symbols not interpret escapes in its input. (string->symbol "mISSISSIppi") Symbols are objects whose usefulness rests on the fact that =⇒ mISSISSIppi two symbols are identical (in the sense of eqv?) if and only (eq? ’bitBlt (string->symbol "bitBlt")) if their names are spelled the same way. For instance, they =⇒ #t can be used the way enumerated values are used in other (eq? ’LollyPop languages. (string->symbol 44 Revised7 Scheme

(symbol->string ’LollyPop))) Characters written in the #\ notation are self-evaluating. =⇒ #t That is, they do not have to be quoted in programs. (string=? "K. Harper, M.D." (symbol->string Some of the procedures that operate on characters ignore (string->symbol "K. Harper, M.D."))) the difference between upper case and lower case. The pro- =⇒ #t cedures that ignore case have “-ci” (for “case insensitive”) embedded in their names.

6.6. Characters (char? obj ) procedure Characters are objects that represent printed characters Returns #t if obj is a character, otherwise returns #f. such as letters and digits. All Scheme implementations must support at least the ASCII character repertoire: that (char=? char1 char2 char3 ... ) procedure is, Unicode characters U+0000 through U+007F. Imple- (char? char1 char2 char3 ... ) procedure see fit, and may also support non-Unicode characters as (char<=? char1 char2 char3 ... ) procedure well. Except as otherwise specified, the result of applying (char>=? char1 char2 char3 ... ) procedure any of the following procedures to a non-Unicode character is implementation-dependent. These procedures return #t if the Unicode scalar values corresponding to their arguments are (respectively): equal, Characters are written using the notation #\hcharacteri or monotonically increasing, monotonically decreasing, mono- #\hcharacter namei or #\xhhex scalar valuei. tonically non-decreasing, or monotonically non-increasing. The following character names must be supported by all These predicates are required to be transitive. implementations with the given values. Implementations are free to add other names. These procedures impose a total ordering on the set of characters which is the same as the Unicode scalar value ordering. This is true whether or not the implementation #\alarm ; U+0007 uses the Unicode representation internally. #\backspace ; U+0008 #\delete ; U+007F (char-ci=? char1 char2 char3 ... ) #\escape ; U+001B char library procedure #\newline ; the linefeed character, U+000A (char-ci? char1 char2 char3 ... ) #\space ; the preferred way to write a space char library procedure #\tab ; the tab character, U+0009 (char-ci<=? char1 char2 char3 ... ) char library procedure Here are some additional examples: (char-ci>=? char1 char2 char3 ... ) char library procedure #\a ; lower case letter These procedures are similar to char=? et cetera, but they #\A ; upper case letter treat upper case and lower case letters as the same. For #\( ; left parenthesis example, (char-ci=? #\A #\a) returns #t. #\ ; the space character Specifically, these procedures behave as if char-foldcase #\x03BB ; λ (if character is supported) were applied to their arguments before they were com- #\iota ; ι (if character and name are supported) pared.

Case is significant in #\hcharacteri, and in #\hcharacter char char library procedure namei, but not in #\xhhex scalar valuei. If hcharacteri in (char-alphabetic? ) char char library procedure #\hcharacteri is alphabetic, then any character immedi- (char-numeric? ) ately following hcharacteri must be a delimiter character (char-whitespace? char) char library procedure such as a space or parenthesis. This rule resolves the am- (char-upper-case? letter) char library procedure biguous case where, for example, the sequence of characters (char-lower-case? letter) char library procedure “#\space” could be taken to be either a representation of These procedures return #t if their arguments are alpha- the space character or a representation of the character betic, numeric, whitespace, upper case, or lower case char- “#\s” followed by a representation of the symbol “pace.” acters, respectively, otherwise they return #f. 6. Standard procedures 45

Specifically, they must return #t when applied to char- lowercase letter does not exist or is not supported by the acters with the Unicode properties Alphabetic, Nu- implementation. See UAX #29 [14] (part of the Unicode meric Digit, White Space, Uppercase, and Lowercase re- Standard) for details. spectively, and #f when applied to any other Unicode char- Note that many Unicode lowercase characters do not have acters. Note that many Unicode characters are alphabetic uppercase equivalents. but neither upper nor lower case.

char char library procedure (digit-value ) 6.7. Strings This procedure returns the numeric value (0 to 9) of its argument if it is a numeric digit (that is, if char-numeric? Strings are sequences of characters. Strings are written as returns #t), or #f on any other character. sequences of characters enclosed within quotation marks (digit-value #\3) =⇒ 3 ("). Within a string literal, various escape sequences rep- (digit-value #\x0664) =⇒ 4 resent characters other than themselves. Escape sequences (digit-value #\x0AE6) =⇒ 0 always start with a backslash (\): (digit-value #\x0EA6) =⇒ #f

• \a : alarm, U+0007 (char->integer char) procedure (integer->char n) procedure • \b : backspace, U+0008 Given a Unicode character, char->integer returns an ex- • \t : character tabulation, U+0009 act integer between 0 and #xD7FF or between #xE000 and #x10FFFF which is equal to the Unicode scalar value of • \n : linefeed, U+000A that character. Given a non-Unicode character, it returns an exact integer greater than . This is true inde- #x10FFFF • \r : return, U+000D pendent of whether the implementation uses the Unicode representation internally. • \" : double quote, U+0022 Given an exact integer that is the value returned by a char- acter when char->integer is applied to it, integer->char • \\ : backslash, U+005C returns that character. • \| : vertical line, U+007C

(char-upcase char) char library procedure • \hintraline whitespacei*hline endingi (char-downcase char) char library procedure hintraline whitespacei* : nothing (char-foldcase char) char library procedure The char-upcase procedure, given an argument that is • \xhhex scalar valuei; : specified character (note the the lowercase part of a Unicode casing pair, returns the terminating semi-colon). uppercase member of the pair, provided that both charac- ters are supported by the Scheme implementation. Note The result is unspecified if any other character in a string that language-sensitive casing pairs are not used. If the occurs after a backslash. argument is not the lowercase member of such a pair, it is returned. Except for a line ending, any character outside of an escape sequence stands for itself in the string literal. A line end- The char-downcase procedure, given an argument that is ing which is preceded by \hintraline whitespacei expands the uppercase part of a Unicode casing pair, returns the to nothing (along with any trailing intraline whitespace), lowercase member of the pair, provided that both charac- and can be used to indent strings for improved legibility. ters are supported by the Scheme implementation. Note Any other line ending has the same effect as inserting a \n that language-sensitive casing pairs are not used. If the character into the string. argument is not the uppercase member of such a pair, it is returned. Examples:

The char-foldcase procedure applies the Unicode simple "The word \"recursion\" has many meanings." case-folding algorithm to its argument and returns the re- "Another example:\ntwo lines of text" sult. Note that language-sensitive folding is not used. If "Here’s text \ the argument is an uppercase letter, the result will be ei- containing just one line" ther a lowercase letter or the same as the argument if the "\x03B1; is named GREEK SMALL LETTER ALPHA." 46 Revised7 Scheme

The length of a string is the number of characters that it (define (f) (make-string 3 #\*)) contains. This number is an exact, non-negative integer (define (g) "***") that is fixed when the string is created. The valid indexes (string-set! (f) 0 #\?) =⇒ unspecified of a string are the exact non-negative integers less than (string-set! (g) 0 #\?) =⇒ error the length of the string. The first character of a string has (string-set! (symbol->string ’immutable) index 0, the second has index 1, and so on. 0 #\?) =⇒ error Some of the procedures that operate on strings ignore the difference between upper and lower case. The names of the versions that ignore case end with “-ci” (for “case (string=? string1 string2 string3 ... ) procedure insensitive”). Returns #t if all the strings are the same length and contain Implementations may forbid certain characters from ap- exactly the same characters in the same positions, other- pearing in strings. However, with the exception of #\null, wise returns #f. ASCII characters must not be forbidden. For exam- ple, an implementation might support the entire Unicode (string-ci=? string1 string2 string3 ... ) repertoire, but only allow characters U+0001 to U+00FF char library procedure (the Latin-1 repertoire) in strings. It is an error to Returns #t if, after case-folding, all the strings are the pass such a forbidden character to make-string, string, same length and contain the same characters in the same string-set!, or string-fill!. positions, otherwise returns #f. Specifically, these proce- dures behave as if string-foldcase were applied to their (string? obj ) procedure arguments before comparing them. Returns #t if obj is a string, otherwise returns #f. (string? string1 string2 string3 ... ) procedure The make-string procedure returns a newly allocated (string-ci>? string1 string2 string3 ... ) string of length k. If char is given, then all the characters char library procedure of the string are initialized to char, otherwise the contents (string<=? string1 string2 string3 ... ) procedure of the string are unspecified. (string-ci<=? string1 string2 string3 ... ) char library procedure (string>=? string1 string2 string3 ... ) procedure (string char ... ) procedure (string-ci>=? string1 string2 string3 ... ) Returns a newly allocated string composed of the argu- char library procedure ments. It is analogous to list. These procedures return #t if their arguments are (respec- tively): equal, monotonically increasing, monotonically de- creasing, monotonically non-decreasing, or monotonically (string-length string) procedure non-increasing. Returns the number of characters in the given string. These predicates are required to be transitive. These procedures compare strings in an implementation- (string-ref string k) procedure defined way. One approach is to make them the lexico- It is an error if k is not a valid index of string. graphic extensions to strings of the corresponding order- ings on characters. In that case, string?, and must satisfy 6. Standard procedures 47 string<=? if and only if they do not satisfy string>? and (string-copy! to at from) procedure string>=? if and only if they do not satisfy stringlist string) procedure contains. This number is a non-negative integer that is (string->list string start) procedure fixed when the vector is created. The valid indexes of a (string->list string start end) procedure vector are the exact non-negative integers less than the (list->string list) procedure length of the vector. The first element in a vector is indexed It is an error if any element of list is not a character. by zero, and the last element is indexed by one less than the length of the vector. The string->list procedure returns a newly allocated list of the characters of string between start and end. list-> Vectors are written using the notation #(obj ... ). For string returns a newly allocated string formed from the example, a vector of length 3 containing the number zero elements in the list list. In both procedures, order is pre- in element 0, the list (2 2 2 2) in element 1, and the served. string->list and list->string are inverses so string "Anna" in element 2 can be written as following: far as equal? is concerned. #(0 (2 2 2 2) "Anna") Vector constants are self-evaluating, so they do not need (string-copy string) procedure to be quoted in programs. (string-copy string start) procedure (string-copy string start end) procedure Returns a newly allocated copy of the part of the given (vector? obj ) procedure string between start and end. Returns #t if obj is a vector; otherwise returns #f. 48 Revised7 Scheme

(make-vector k) procedure (vector->list ’#(dah dah didah)) (make-vector k fill) procedure =⇒ (dah dah didah) (vector->list ’#(dah dah didah) 1 2) Returns a newly allocated vector of k elements. If a second =⇒ (dah) argument is given, then each element is initialized to fill. (list->vector ’(dididit dah)) Otherwise the initial contents of each element is unspeci- =⇒ #(dididit dah) fied.

(vector obj ... ) procedure (vector->string vector) procedure (vector->string vector start) procedure Returns a newly allocated vector whose elements contain (vector->string vector start end) procedure the given arguments. It is analogous to list. (string->vector string) procedure (vector ’a ’b ’c) =⇒ #(a b c) (string->vector string start) procedure (string->vector string start end) procedure (vector-length vector) procedure It is an error if any element of vector between start and end is not a character, or is a character forbidden in strings. Returns the number of elements in vector as an exact in- teger. The vector->string procedure returns a newly allocated string of the objects contained in the elements of vector between start and end. The procedure (vector-ref vector k) procedure string->vector returns a newly created vector initialized to the elements It is an error if k is not a valid index of vector. of the string string between start and end. The vector-ref procedure returns the contents of element In both procedures, order is preserved. k of vector. (string->vector "ABC") =⇒ #(#\A #\B #\C) (vector-ref ’#(1 1 2 3 5 8 13 21) (vector->string 5) #(#\1 #\2 #\3) =⇒ "123" =⇒ 8 (vector-ref ’#(1 1 2 3 5 8 13 21) (exact (round (* 2 (acos -1))))) (vector-copy vector) procedure =⇒ 13 (vector-copy vector start) procedure (vector-copy vector start end) procedure (vector-set! vector k obj ) procedure Returns a newly allocated copy of the elements of the given It is an error if k is not a valid index of vector. vector between start and end. The elements of the new The vector-set! procedure stores obj in element k of vector are the same (in the sense of eqv?) as the elements vector. of the old.

(let ((vec (vector 0 ’(2 2 2 2) "Anna"))) (define a #(1 8 2 8)) ; a may be immutable (vector-set! vec 1 ’("Sue" "Sue")) (define b (vector-copy a)) vec) (vector-set! b 0 3) ; b is mutable =⇒ #(0 ("Sue" "Sue") "Anna") b =⇒ #(3 8 2 8) (define c (vector-copy b 1 3)) (vector-set! ’#(0 1 2) 1 "doe") c =⇒ #(8 2) =⇒ error ; constant vector

(vector->list vector) procedure (vector-copy! to at from) procedure (vector->list vector start) procedure (vector-copy! to at from start) procedure (vector->list vector start end) procedure (vector-copy! to at from start end) procedure (list->vector list) procedure It is an error if at is less than zero or greater than the length The vector->list procedure returns a newly allocated list of to. It is also an error if (- (vector-length to) at) is less of the objects contained in the elements of vector between than (- end start). start and end. The list->vector procedure returns a Copies the elements of vector from between start and end newly created vector initialized to the elements of the list to vector to, starting at at. The order in which elements list. are copied is unspecified, except that if the source and des- In both procedures, order is preserved. tination overlap, copying takes place as if the source is first 6. Standard procedures 49 copied into a temporary vector and then into the destina- (make-bytevector k) procedure tion. This can be achieved without allocating storage by (make-bytevector k byte) procedure making sure to copy in the correct direction in such cir- The make-bytevector procedure returns a newly allocated cumstances. bytevector of length k. If byte is given, then all elements (define a (vector 1 2 3 4 5)) of the bytevector are initialized to byte, otherwise the con- (define b (vector 10 20 30 40 50)) tents of each element are unspecified. (vector-copy! b 1 a 0 2) (make-bytevector 2 12) =⇒ #u8(12 12) b =⇒ #(10 1 2 40 50)

(bytevector byte ... ) procedure (vector-append vector ... ) procedure Returns a newly allocated bytevector containing its argu- Returns a newly allocated vector whose elements are the ments. concatenation of the elements of the given vectors. (bytevector 1 3 5 1 3 5) =⇒ #u8(1 3 5 1 3 5) (vector-append #(a b c) #(d e f)) (bytevector) =⇒ #u8() =⇒ #(a b c d e f)

(bytevector-length bytevector) procedure (vector-fill! vector fill) procedure (vector-fill! vector fill start) procedure Returns the length of bytevector in bytes as an exact inte- (vector-fill! vector fill start end) procedure ger. The vector-fill! procedure stores fill in the elements of vector between start and end. (bytevector-u8-ref bytevector k) procedure It is an error if k is not a valid index of bytevector. (define a (vector 1 2 3 4 5)) (vector-fill! a ’smash 2 4) Returns the kth byte of bytevector. a =⇒ #(1 2 smash smash 5) (bytevector-u8-ref ’#u8(1 1 2 3 5 8 13 21) 5) =⇒ 8 6.9. Bytevectors (bytevector-u8-set! bytevector k byte) procedure Bytevectors represent blocks of binary data. They are It is an error if k is not a valid index of bytevector. fixed-length sequences of bytes, where a byte is an exact integer in the range [0, 255]. A bytevector is typically more Stores byte as the kth byte of bytevector. space-efficient than a vector containing the same values. (let ((bv (bytevector 1 2 3 4) (bytevector-u8-set! bv 1 3) The length of a bytevector is the number of elements that bv) it contains. This number is a non-negative integer that is =⇒ #u8(1 3 3 4) fixed when the bytevector is created. The valid indexes of a bytevector are the exact non-negative integers less than the length of the bytevector, starting at index zero as with (bytevector-copy bytevector) procedure vectors. (bytevector-copy bytevector start) procedure (bytevector-copy bytevector start end) procedure Bytevectors are written using the notation #u8(byte ... ). For example, a bytevector of length 3 containing the byte Returns a newly allocated bytevector containing the bytes 0 in element 0, the byte 10 in element 1, and the byte 5 in in bytevector between start and end. element 2 can be written as following: (define a #u8(1 2 3 4 5)) (bytevector-copy a 2 4)) =⇒ #u8(3 4) #u8(0 10 5) Bytevector constants are self-evaluating, so they do not to at from procedure need to be quoted in programs. (bytevector-copy! ) (bytevector-copy! to at from start) procedure (bytevector-copy! to at from start end) procedure (bytevector? obj ) procedure It is an error if at is less than zero or greater than the length Returns #t if obj is a bytevector. Otherwise, #f is returned. of to. It is also an error if (- (bytevector-length to) at) is less than (- end start). 50 Revised7 Scheme

Copies the bytes of bytevector from between start and end (procedure? car) =⇒ #t to bytevector to, starting at at. The order in which bytes (procedure? ’car) =⇒ #f are copied is unspecified, except that if the source and des- (procedure? (lambda (x) (* x x))) tination overlap, copying takes place as if the source is first =⇒ #t copied into a temporary bytevector and then into the des- (procedure? ’(lambda (x) (* x x))) tination. This can be achieved without allocating storage =⇒ #f (call-with-current-continuation procedure?) by making sure to copy in the correct direction in such =⇒ #t circumstances.

(define a (bytevector 1 2 3 4 5)) (define b (bytevector 10 20 30 40 50)) (apply proc arg1 ... args) procedure (bytevector-copy! b 1 a 0 2) The apply procedure calls proc with the elements of the list b =⇒ #u8(10 1 2 40 50) (append (list arg1 ... ) args) as the actual arguments.

(apply + (list 3 4)) =⇒ 7 (bytevector-append bytevector ... ) procedure Returns a newly allocated bytevector whose elements are (define compose the concatenation of the elements in the given bytevectors. (lambda (f g) (lambda args (bytevector-append #u8(0 1 2) #u8(3 4 5)) (f (apply g args))))) =⇒ #u8(0 1 2 3 4 5) ((compose sqrt *) 12 75) =⇒ 30

(utf8->string bytevector) procedure (utf8->string bytevector start) procedure (map proc list1 list2 ... ) procedure (utf8->string bytevector start end) procedure It is an error if proc does not accept as many arguments as there (string->utf8 string) procedure are lists and return a single value. (string->utf8 string start) procedure (string->utf8 string start end) procedure The map procedure applies proc element-wise to the ele- ments of the lists and returns a list of the results, in order. It is an error for bytevector to contain invalid UTF-8 byte se- If more than one list is given and not all lists have the quences or byte sequences representing characters which are same length, map terminates when the shortest list runs forbidden in strings. out. The lists may be circular, but it is an error if they These procedures translate between strings and bytevec- are all circular. It is an error for proc to mutate any of tors that encode those strings using the UTF-8 encod- the lists. The dynamic order in which proc is applied to ing. The utf8->string procedure decodes the bytes of the elements of the lists is unspecified. If multiple returns a bytevector between start and end and returns the corre- occur from map, the values returned by earlier returns are sponding string; the string->utf8 procedure encodes the not mutated. characters of a string between start and end and returns (map cadr ’((a b) (d e) (g h))) the corresponding bytevector. =⇒ (b e h) (utf8->string #u8(#x41)) =⇒ "A" (string->utf8 "λ") =⇒ #u8(#xCE #xBB) (map (lambda (n) (expt n n)) ’(1 2 3 4 5)) =⇒ (1 4 27 256 3125)

6.10. Control features (map + ’(1 2 3) ’(4 5 6 7)) =⇒ (5 7 9)

This section describes various primitive procedures which (let ((count 0)) control the flow of program execution in special ways. Pro- (map (lambda (ignored) cedures in this section that invoke procedure arguments al- (set! count (+ count 1)) ways do so in the same dynamic environment as the call of count) the original procedure. The procedure? predicate is also ’(a b))) =⇒ (1 2) or (2 1) described here.

(string-map proc string1 string2 ... ) procedure (procedure? obj ) procedure It is an error if proc does not accept as many arguments as there Returns #t if obj is a procedure, otherwise returns #f. are strings and return a single character. 6. Standard procedures 51

The string-map procedure applies proc element-wise to The arguments to for-each are like the arguments to map, the elements of the strings and returns a string of the re- but for-each calls proc for its side effects rather than for sults, in order. If more than one string is given and not its values. Unlike map, for-each is guaranteed to call proc all strings have the same length, string-map terminates on the elements of the lists in order from the first ele- when the shortest string runs out. The dynamic order in ment(s) to the last, and the value returned by for-each which proc is applied to the elements of the strings is un- is unspecified. If more than one list is given and not all specified. If multiple returns occur from string-map, the lists have the same length, for-each terminates when the values returned by earlier returns are not mutated. shortest list runs out. The lists may be circular, but it is (string-map char-foldcase "AbdEgH") an error if they are all circular. =⇒ "abdegh" It is an error for proc to mutate any of the lists.

(string-map (let ((v (make-vector 5))) (lambda (c) (for-each (lambda (i) (integer->char (+ 1 (char->integer c)))) (vector-set! v i (* i i))) "HAL") ’(0 1 2 3 4)) =⇒ =⇒ "IBM" v) #(0 1 4 9 16)

(string-map (string-for-each proc string1 string2 ... ) procedure (lambda (c k) It is an error if proc does not accept as many arguments as there ((if (eqv? k #\u) char-upcase char-downcase) c)) are strings. "studlycaps xxx" The arguments to string-for-each are like the arguments "ululululul") to string-map, but string-for-each calls proc for its =⇒ "StUdLyCaPs" side effects rather than for its values. Unlike string-map, string-for-each is guaranteed to call proc on the ele- (vector-map proc vector1 vector2 ... ) procedure ments of the lists in order from the first element(s) to It is an error if proc does not accept as many arguments as there the last, and the value returned by string-for-each is are vectors and return a single value. unspecified. If more than one string is given and not all strings have the same length, string-for-each terminates The vector-map procedure applies proc element-wise to when the shortest string runs out. It is an error for proc the elements of the vectors and returns a vector of the to mutate any of the strings. results, in order. If more than one vector is given and not all vectors have the same length, vector-map terminates (let ((v ’())) when the shortest vector runs out. The dynamic order (string-for-each in which proc is applied to the elements of the vectors is (lambda (c) (set! v (cons (char->integer c) v))) unspecified. If multiple returns occur from vector-map, "abcde") v) =⇒ (101 100 99 98 97) the values returned by earlier returns are not mutated. (vector-map cadr ’#((a b) (d e) (g h))) proc vector vector ... procedure =⇒ #(b e h) (vector-for-each 1 2 ) It is an error if proc does not accept as many arguments as there (vector-map (lambda (n) (expt n n)) are vectors. ’#(1 2 3 4 5)) The arguments to are like the arguments =⇒ #(1 4 27 256 3125) vector-for-each to vector-map, but vector-for-each calls proc for its (vector-map + ’#(1 2 3) ’#(4 5 6 7)) side effects rather than for its values. Unlike vector-map, =⇒ #(5 7 9) vector-for-each is guaranteed to call proc on the ele- ments of the vectors in order from the first element(s) to (let ((count 0)) the last, and the value returned by vector-for-each is un- (vector-map specified. If more than one vector is given and not all vec- (lambda (ignored) tors have the same length, vector-for-each terminates (set! count (+ count 1)) when the shortest vector runs out. It is an error for proc count) to mutate any of the vectors. ’#(a b))) =⇒ #(1 2) or #(2 1) (let ((v (make-list 5))) (vector-for-each (for-each proc list list ... ) procedure 1 2 (lambda (i) (list-set! v i (* i i))) It is an error if proc does not accept as many arguments as there ’#(0 1 2 3 4)) are lists. v) =⇒ (0 1 4 9 16) 52 Revised7 Scheme

(call-with-current-continuation proc) procedure ((pair? obj) (call/cc proc) procedure (+ (r (cdr obj)) 1)) (else (return #f)))))) It is an error if proc does not accept one argument. (r obj)))))) The procedure call-with-current-continuation (or its equivalent abbreviation call/cc) packages the current (list-length ’(1 2 3 4)) =⇒ 4 continuation (see the rationale below) as an “escape pro- cedure” and passes it as an argument to proc. The escape (list-length ’(a b . c)) =⇒ #f procedure is a Scheme procedure that, if it is later called, Rationale: will abandon whatever continuation is in effect at that later A common use of call-with-current-continuation is for time and will instead use the continuation that was in ef- structured, non-local exits from loops or procedure bodies, but fect when the escape procedure was created. Calling the in fact call-with-current-continuation is useful for imple- escape procedure will cause the invocation of before and menting a wide variety of advanced control structures. In fact, after thunks installed using dynamic-wind. raise and guard provide a more structured mechanism for non- local exits. The escape procedure accepts the same number of ar- guments as the continuation to the original call to Whenever a Scheme expression is evaluated there is a contin- call-with-current-continuation. Except for continu- uation wanting the result of the expression. The continuation ations created by the call-with-values procedure (in- represents an entire (default) future for the computation. If the expression is evaluated at the REPL, for example, then the con- cluding the initialization expressions of define-values, tinuation might take the result, print it on the screen, prompt let-values, and let*-values expressions), all continu- for the next input, evaluate it, and so on forever. Most of the ations take exactly one value. The effect of passing no time the continuation includes actions specified by user code, value or more than one value to continuations that were as in a continuation that will take the result, multiply it by not created by call-with-values is unspecified. the value stored in a local variable, add seven, and give the an- However, the continuations of all non-final expressions swer to the REPL’s continuation to be printed. Normally these within a sequence of expressions, such as in lambda, ubiquitous continuations are hidden behind the scenes and pro- grammers do not think much about them. On rare occasions, case-lambda, begin, let, let*, letrec, letrec*, however, a programmer needs to deal with continuations explic- let-values, let*-values, let-syntax, letrec-syntax, itly. The call-with-current-continuation procedure allows parameterize, guard, case, cond, when, and unless ex- Scheme programmers to do that by creating a procedure that pressions, take an arbitrary number of values because they acts just like the current continuation. discard the values passed to them in any event. The escape procedure that is passed to proc has unlimited (values obj ...) procedure extent just like any other procedure in Scheme. It can be Delivers all of its arguments to its continuation. The stored in variables or data structures and can be called as values procedure might be defined as follows: many times as desired. However, like the raise and error (define (values . things) procedures, it never returns to its caller. (call-with-current-continuation The following examples show only the simplest ways (lambda (cont) (apply cont things)))) in which call-with-current-continuation is used. If all real uses were as simple as these examples, there (call-with-values producer consumer) procedure would be no need for a procedure with the power of Calls its producer argument with no values and a contin- call-with-current-continuation. uation that, when passed some values, calls the consumer (call-with-current-continuation procedure with those values as arguments. The continua- (lambda (exit) tion for the call to consumer is the continuation of the call (for-each (lambda (x) to call-with-values. (if (negative? x) (exit x))) (call-with-values (lambda () (values 4 5)) ’(54 0 37 -3 245 19)) (lambda (a b) b)) #t)) =⇒ -3 =⇒ 5

(define list-length (call-with-values * -) =⇒ -1 (lambda (obj) (call-with-current-continuation (dynamic-wind before thunk after) procedure (lambda (return) (letrec ((r Calls thunk without arguments, returning the result(s) of (lambda (obj) this call. Before and after are called, also without ar- (cond ((null? obj) 0) guments, as required by the following rules. Note that, 6. Standard procedures 53 in the absence of calls to continuations captured using ’talk1)))) call-with-current-continuation, the three arguments (lambda () (add ’disconnect))) are called once each, in order. Before is called whenever (if (< (length path) 4) execution enters the dynamic extent of the call to thunk (c ’talk2) and after is called whenever it exits that dynamic extent. (reverse path)))) The dynamic extent of a procedure call is the period be- =⇒ (connect talk1 disconnect tween when the call is initiated and when it returns. The connect talk2 disconnect) before and after thunks are called in the same dynamic environment as the call to dynamic-wind. In Scheme, be- cause of call-with-current-continuation, the dynamic 6.11. Exceptions extent of a call is not always a single, connected time pe- riod. It is defined as follows: This section describes Scheme’s exception-handling and exception-raising procedures. For the concept of Scheme • The dynamic extent is entered when execution of the exceptions, see section 1.3.2. See also 4.2.7 for the guard body of the called procedure begins. syntax.

• The dynamic extent is also entered when exe- Exception handlers are one-argument procedures that de- cution is not within the dynamic extent and a termine the action the program takes when an exceptional continuation is invoked that was captured (using situation is signaled. The system implicitly maintains a call-with-current-continuation) during the dy- current exception handler in the dynamic environment. namic extent. The program raises an exception by invoking the current exception handler, passing it an object encapsulating in- • It is exited when the called procedure returns. formation about the exception. Any procedure accepting • It is also exited when execution is within the dynamic one argument can serve as an exception handler and any extent and a continuation is invoked that was captured object may be used to represent an exception. while not within the dynamic extent. (with-exception-handler handler thunk) procedure If a second call to dynamic-wind occurs within the dynamic It is an error if handler does not accept one argument. It is also extent of the call to thunk and then a continuation is in- an error if thunk does not accept zero arguments. voked in such a way that the afters from these two invoca- The with-exception-handler procedure returns the re- tions of dynamic-wind are both to be called, then the after sults of invoking thunk. Handler is installed as the current associated with the second (inner) call to dynamic-wind is exception handler in the dynamic environment used for the called first. invocation of thunk. If a second call to dynamic-wind occurs within the dy- (call-with-current-continuation namic extent of the call to thunk and then a continua- (lambda (k) tion is invoked in such a way that the befores from these (with-exception-handler two invocations of dynamic-wind are both to be called, (lambda (x) then the before associated with the first (outer) call to (display "condition: ") dynamic-wind is called first. (write x) If invoking a continuation requires calling the before from (newline) (k ’exception)) one call to and the after from another, then dynamic-wind (lambda () the after is called first. (+ 1 (raise ’an-error)))))) The effect of using a captured continuation to enter or exit =⇒ exception the dynamic extent of a call to before or after is unspecified. and prints condition: an error (call-with-current-continuation (let ((path ’()) (lambda (k) (c #f)) (with-exception-handler (let ((add (lambda (s) (lambda (x) (set! path (cons s path))))) (display "something went wrong") (dynamic-wind (newline) (lambda () (add ’connect)) ’dont-care) (lambda () (lambda () (add (call-with-current-continuation (+ 1 (raise ’an-error)))))) (lambda (c0) =⇒ unspecified (set! c c0) and prints something went wrong 54 Revised7 Scheme

After printing, the second example then raises another ex- (error-object? obj ) procedure ception. Returns #t if obj is an object created by error or one of an implementation-defined set of objects. Otherwise, (raise obj ) procedure it returns #f. The objects used to signal errors, includ- ing those which satisfy the predicates file-error? and Raises an exception by invoking the current exception han- read-error?, may or may not satisfy error-object?. dler on obj . The handler is called with the same dynamic environment as that of the call to raise, except that the current exception handler is the one that was in place when (error-object-message error-object) procedure the handler being called was installed. If the handler re- turns, a secondary exception is raised in the same dynamic Returns the message encapsulated by error-object. environment as the handler. The relationship between obj and the object raised by the secondary exception is unspec- (error-object-irritants error-object) procedure ified. Returns a list of the irritants encapsulated by error-object.

(raise-continuable obj ) procedure Raises an exception by invoking the current exception han- (read-error? obj ) procedure dler on obj . The handler is called with the same dynamic (file-error? obj ) procedure environment as the call to raise-continuable, except Error type predicates. Returns #t if obj is an object raised that: (1) the current exception handler is the one that was by the read procedure or by the inability to open an input in place when the handler being called was installed, and or output port on a file, respectively. Otherwise, it returns (2) if the handler being called returns, then it will again #f. become the current exception handler. If the handler re- turns, the values it returns become the values returned by the call to raise-continuable. 6.12. Environments and evaluation (with-exception-handler (lambda (con)

(cond (environment list1 ... ) eval library procedure ((string? con) (display con)) This procedure returns a specifier for the environment that (else results by starting with an empty environment and then (display "a warning has been issued"))) importing each list, considered as an import set, into it. 42) (See section 5.6 for a description of import sets.) The (lambda () bindings of the environment represented by the specifier (+ (raise-continuable "should be a number") are immutable, as is the environment itself. 23))) prints: should be a number =⇒ 65 (scheme-report-environment version) r5rs library procedure (error message obj ...) procedure If version is equal to 5, corresponding to R5RS, scheme-report-environment returns a specifier for an en- Message should be a string. vironment that contains only the bindings defined in the Raises an exception as if by calling raise on a newly al- R5RS library. Implementations must support this value of located implementation-defined object which encapsulates version. the information provided by message, as well as any obj s, Implementations may also support other values of version, known as the irritants. The procedure error-object? in which case they return a specifier for an environment must return #t on such objects. containing bindings corresponding to the specified version (define (null-list? l) of the report. If version is neither 5 nor another value (cond ((pair? l) #f) supported by the implementation, an error is signaled. ((null? l) #t) (else The effect of defining or assigning (through the use of eval) (error an identifier bound in a scheme-report-environment (for "null-list?: argument out of domain" example car) is unspecified. Thus both the environment l)))) and the bindings it contains may be immutable. 6. Standard procedures 55

(null-environment version) r5rs library procedure Different port types operate on different data. Scheme implementations are required to support textual ports and If version is equal to 5, corresponding to R5RS, the binary ports, but may also provide other port types. null-environment procedure returns a specifier for an en- vironment that contains only the bindings for all syntactic A textual port supports reading or writing of individual keywords defined in the R5RS library. Implementations characters from or to a backing store containing characters must support this value of version. using read-char and write-char below, and it supports operations defined in terms of characters, such as and Implementations may also support other values of version, read . in which case they return a specifier for an environment write containing appropriate bindings corresponding to the spec- A binary port supports reading or writing of individual ified version of the report. If version is neither 5 nor an- bytes from or to a backing store containing bytes using other value supported by the implementation, an error is read-u8 and write-u8 below, as well as operations defined signaled. in terms of bytes. Whether the textual and binary port types are disjoint is implementation-dependent. The effect of defining or assigning (through the use of eval) an identifier bound in a scheme-report-environment (for Ports can be used to access files, devices, and similar things example car) is unspecified. Thus both the environment on the host system on which the Scheme program is run- and the bindings it contains may be immutable. ning.

(interaction-environment) repl library procedure (call-with-port port proc) procedure This procedure returns a specifier for an environment that It is an error if proc does not accept one argument. contains an implementation-defined set of bindings, typi- The call-with-port procedure calls proc with port as an cally a superset of those exported by (scheme base). The argument. If proc returns, then the port is closed auto- intent is that this procedure will return the environment matically and the values yielded by the proc are returned. in which the implementation would evaluate expressions If proc does not return, then the port must not be closed entered by the user into a REPL. automatically unless it is possible to prove that the port will never again be used for a read or write operation. (eval expr-or-def environment-specifier) Rationale: Because Scheme’s escape procedures have unlimited eval library procedure extent, it is possible to escape from the current continuation If expr-or-def is an expression, it is evaluated in the speci- but later to resume it. If implementations were permitted to fied environment and its values are returned. If it is a defi- close the port on any escape from the current continuation, nition, the specified identifier(s) are defined in the specified then it would be impossible to write portable code using both environment, provided the environment is not immutable. call-with-current-continuation and call-with-port. Implementations may extend eval to allow other objects. string proc (eval ’(* 7 3) (environment ’(scheme base))) (call-with-input-file ) =⇒ 21 file library procedure (call-with-output-file string proc) (let ((f (eval ’(lambda (f x) (f x x)) file library procedure (null-environment 5)))) It is an error if proc does not accept one argument. (f + 10)) =⇒ 20 These procedures obtain a textual port obtained by (eval ’(define foo 32) opening the named file for input or output as if by (environment ’(scheme base))) open-input-file or open-output-file. The port and =⇒ error is signaled proc are then passed to a procedure equivalent to call-with-port. 6.13. Input and output (input-port? obj ) procedure (output-port? obj ) procedure 6.13.1. Ports (textual-port? obj ) procedure Ports represent input and output devices. To Scheme, an (binary-port? obj ) procedure input port is a Scheme object that can deliver data upon (port? obj ) procedure command, while an output port is a Scheme object that can These procedures return #t if obj is an input port, out- accept data. Whether the input and output port types are put port, textual port, binary port, or any kind of port, disjoint is implementation-dependent. respectively. Otherwise they return #f. 56 Revised7 Scheme

(input-port-open? port) procedure apply the last two procedures to a port which is not an (output-port-open? port) procedure input or output port, respectively. Scheme implementa- Returns #t if port is still open and capable of performing tions may provide ports which are simultaneously input input or output, respectively, and #f otherwise. and output ports, such as sockets; the close-input-port and close-output-port procedures can then be used to close the input and output sides of the port independently. (current-input-port) procedure (current-output-port) procedure These routines have no effect if the port has already been (current-error-port) procedure closed. Returns the current default input port, output port, or error port (an output port), respectively. These proce- (open-input-string string) procedure dures are parameter objects, which can be overridden with parameterize (see section 4.2.6). The initial bindings for Takes a string and returns a textual input port that delivers these are implementation-defined textual ports. characters from the string. If the string is modified, the effect is unspecified. (with-input-from-file string thunk) file library procedure (open-output-string) procedure (with-output-to-file string thunk) file library procedure Returns a textual output port that will accumulate char- acters for retrieval by get-output-string. The file is opened for input or output as if by open-input-file or open-output-file, and the new port is made to be the value returned by current-input-port (get-output-string port) procedure or current-output-port (as used by (read), (write obj ), and so forth). The thunk is then called with no It is an error if port was not created with open-output-string. arguments. When the thunk returns, the port is closed Returns a string consisting of the characters that have been and the previous default is restored. It is an error if thunk output to the port so far in the order they were output. If does not accept zero arguments. Both procedures return the result string is modified, the effect is unspecified. the values yielded by thunk. If an escape procedure is used to escape from the continuation of these procedures, they (parameterize behave exactly as if the current input or output port had ((current-output-port (open-output-string))) been bound dynamically with parameterize. (display "piece") (display " by piece ") (open-input-file string) file library procedure (display "by piece.") (open-binary-input-file string) file library procedure (newline) Takes a string for an existing file and returns a textual (get-output-string (current-output-port))) input port or binary input port that is capable of delivering =⇒ data from the file. If the file does not exist or cannot be "piece by piece by piece.\n" opened, an error that satisfies file-error? is signaled. (open-input-bytevector bytevector) procedure (open-output-file string) file library procedure (open-binary-output-file string) Takes a bytevector and returns a binary input port that file library procedure delivers bytes from the bytevector. Takes a string naming an output file to be created and re- turns a textual output port or binary output port that is (open-output-bytevector) procedure capable of writing data to a new file by that name. If a file with the given name already exists, the effect is unspec- Returns a binary output port that will accumulate bytes ified. If the file cannot be opened, an error that satisfies for retrieval by get-output-bytevector. file-error? is signaled. (get-output-bytevector port) procedure (close-port port) procedure (close-input-port port) procedure It is an error if port was not created with (close-output-port port) procedure open-output-bytevector. Closes the resource associated with port, rendering the port Returns a bytevector consisting of the bytes that have been incapable of delivering or accepting data. It is an error to output to the port so far in the order they were output. 6. Standard procedures 57

6.13.2. Input character. If an end of line is read, a string containing all of the text up to (but not including) the end of line is re- If port is omitted from any input procedure, it defaults turned, and the port is updated to point just past the end to the value returned by (current-input-port). It is an of line. If an end of file is encountered before any end of error to attempt an input operation on a closed port. line is read, but some characters have been read, a string containing those characters is returned. If an end of file is (read) read library procedure encountered before any characters are read, an end-of-file (read port) read library procedure object is returned. For the purpose of this procedure, an The read procedure converts external representations of end of line consists of either a linefeed character, a carriage Scheme objects into the objects themselves. That is, it is return character, or a sequence of a carriage return charac- a parser for the non-terminal hdatumi (see sections 7.1.2 ter followed by a linefeed character. Implementations may and 6.4). It returns the next object parsable from the also recognize other end of line characters or sequences. given textual input port, updating port to point to the first character past the end of the external representation (eof-object? obj ) procedure of the object. Returns #t if obj is an end-of-file object, otherwise returns Implementations may support extended syntax to repre- #f. The precise set of end-of-file objects will vary among sent record types or other types that do not have datum implementations, but in any case no end-of-file object will representations. ever be an object that can be read in using read. If an end of file is encountered in the input before any characters are found that can begin an object, then an (eof-object) procedure end-of-file object is returned. The port remains open, and further attempts to read will also return an end-of-file ob- Returns an end-of-file object, not necessarily unique. ject. If an end of file is encountered after the beginning of an object’s external representation, but the external repre- (char-ready?) procedure sentation is incomplete and therefore not parsable, an error (char-ready? port) procedure that satisfies read-error? is signaled. Returns #t if a character is ready on the textual input port and returns #f otherwise. If char-ready returns #t (read-char) procedure then the next read-char operation on the given port is (read-char port) procedure guaranteed not to hang. If the port is at end of file then Returns the next character available from the textual input char-ready? returns #t. port, updating the port to point to the following character. Rationale: The char-ready? procedure exists to make it pos- If no more characters are available, an end-of-file object is sible for a program to accept characters from interactive ports returned. without getting stuck waiting for input. Any input editors as- sociated with such ports must ensure that characters whose (peek-char) procedure existence has been asserted by char-ready? cannot be removed (peek-char port) procedure from the input. If char-ready? were to return #f at end of file, a port at end-of-file would be indistinguishable from an Returns the next character available from the textual in- interactive port that has no ready characters. put port, but without updating the port to point to the following character. If no more characters are available, an end-of-file object is returned. (read-string k) procedure (read-string k port) procedure Note: The value returned by a call to peek-char is the same as the value that would have been returned by a call to read-char Reads the next k characters, or as many as are available with the same port. The only difference is that the very next call before the end of file, from the textual input port into a to read-char or peek-char on that port will return the value newly allocated string in left-to-right order and returns the returned by the preceding call to peek-char. In particular, a string. If no characters are available before the end of file, call to peek-char on an interactive port will hang waiting for an end-of-file object is returned. input whenever a call to read-char would have hung. (read-u8) procedure (read-line) procedure (read-u8 port) procedure (read-line port) procedure Returns the next byte available from the binary input port, Returns the next line of text available from the textual updating the port to point to the following byte. If no more input port, updating the port to point to the following bytes are available, an end-of-file object is returned. 58 Revised7 Scheme

(peek-u8) procedure If obj contains cycles which would cause an infinite loop (peek-u8 port) procedure using the normal written representation, then at least the objects that form part of the cycle must be represented Returns the next byte available from the binary input port, using datum labels as described in section 2.4. Datum but without updating the port to point to the following labels must not be used if there are no cycles. byte. If no more bytes are available, an end-of-file object is returned. Implementations may support extended syntax to repre- sent record types or other types that do not have datum representations. (u8-ready?) procedure (u8-ready? port) procedure The write procedure returns an unspecified value. Returns #t if a byte is ready on the binary input port and returns #f otherwise. If u8-ready? returns #t then the (write-shared obj ) write library procedure next read-u8 operation on the given port is guaranteed (write-shared obj port) write library procedure not to hang. If the port is at end of file then u8-ready? The write-shared procedure is the same as write, except returns #t. that shared structure must be represented using datum labels for all pairs and vectors that appear more than once in the output. (read-bytevector k) procedure (read-bytevector k port) procedure (write-simple obj ) write library procedure Reads the next k bytes, or as many as are available before (write-simple obj port) write library procedure the end of file, from the binary input port into a newly allocated bytevector in left-to-right order and returns the The write-simple procedure is the same as write, except bytevector. If no bytes are available before the end of file, that shared structure is never represented using datum la- an end-of-file object is returned. bels. This can cause write-simple not to terminate if obj contains circular structure.

(read-bytevector! bytevector) procedure (read-bytevector! bytevector port) procedure (display obj ) write library procedure (read-bytevector! bytevector port start) procedure (display obj port) write library procedure (read-bytevector! bytevector port start end) Writes a representation of obj to the given textual output procedure port. Strings that appear in the written representation Reads the next end − start bytes, or as many as are avail- are output as if by write-string instead of by write. able before the end of file, from the binary input port Symbols are not escaped. Character objects appear in the into bytevector in left-to-right order beginning at the start representation as if written by write-char instead of by position. If end is not supplied, reads until the end of write. bytevector has been reached. If start is not supplied, reads The display representation of other objects is unspecified. beginning at position 0. Returns the number of bytes read. However, display must not loop forever on self-referencing If no bytes are available, an end-of-file object is returned. pairs, vectors, or records. Thus if the normal write rep- resentation is used, datum labels are needed to represent cycles as in write. 6.13.3. Output Implementations may support extended syntax to repre- If port is omitted from any output procedure, it defaults sent record types or other types that do not have datum to the value returned by (current-output-port). It is an representations. error to attempt an output operation on a closed port. The display procedure returns an unspecified value.

(write obj ) write library procedure Rationale: The write procedure is intended for producing (write obj port) write library procedure machine-readable output and display for producing human- readable output. Writes a representation of obj to the given textual output port. Strings that appear in the written representation are enclosed in quotation marks, and within those strings (newline) procedure backslash and quotation mark characters are escaped by (newline port) procedure backslashes. Symbols that contain non-ASCII characters Writes an end of line to textual output port. Exactly how are escaped with vertical lines. Character objects are writ- this is done differs from one to another. ten using the #\ notation. Returns an unspecified value. 6. Standard procedures 59

(write-char char) procedure It is unspecified whether the results of the expres- (write-char char port) procedure sions are printed. The load procedure does not af- Writes the character char (not an external representation fect the values returned by current-input-port and of the character) to the given textual output port and re- current-output-port. It returns an unspecified value. turns an unspecified value. Rationale: For portability, load must operate on source files. Its operation on other kinds of files necessarily varies among implementations. (write-string string) procedure (write-string string port) procedure (write-string string port start) procedure (file-exists? filename) file library procedure (write-string string port start end) procedure It is an error if filename is not a string. Writes the characters of string from start to end in left-to- The file-exists? procedure returns #t if the named file right order to the textual output port. exists at the time the procedure is called, and #f otherwise.

(write-u8 byte) procedure (delete-file filename) file library procedure (write-u8 byte port) procedure It is an error if filename is not a string. Writes the byte to the given binary output port and returns The delete-file procedure deletes the named file if it an unspecified value. exists and can be deleted, and returns an unspecified value. If the file does not exist or cannot be deleted, an error that (write-bytevector bytevector) procedure satisfies file-error? is signaled. (write-bytevector bytevector port) procedure (write-bytevector bytevector port start) procedure (command-line) process-context library procedure (write-bytevector bytevector port start end) procedure Returns the command line passed to the process as a list of strings. The first string corresponds to the command Writes the bytes of bytevector from start to end in left-to- name, and is implementation-dependent. It is an error to right order to the binary output port. mutate any of these strings.

(flush-output-port) procedure (exit) process-context library procedure (flush-output-port port) procedure (exit obj ) process-context library procedure Flushes any buffered output from the buffer of output-port Runs all outstanding dynamic-wind after procedures, ter- to the underlying file or device and returns an unspecified minates the running program, and communicates an exit value. value to the operating system. If no argument is supplied, or if obj is #t, the exit procedure should communicate 6.14. System interface to the operating system that the program exited normally. If obj is #f, the exit procedure should communicate to the operating system that the program exited abnormally. Questions of system interface generally fall outside of the Otherwise, exit should translate obj into an appropriate domain of this report. However, the following operations exit value for the operating system, if possible. are important enough to deserve description here. The exit procedure must not signal an exception or return to its continuation. (load filename) load library procedure (load filename environment-specifier) Note: Because of the requirement to run handlers, this proce- load library procedure dure is not just the operating system’s exit procedure. It is an error if filename is not a string. (emergency-exit) process-context library procedure An implementation-dependent operation is used to trans- (emergency-exit obj ) process-context library procedure form filename into the name of an existing file con- taining Scheme source code. The load procedure reads Terminates the program without running any outstanding expressions and definitions from the file and evalu- dynamic-wind after procedures and communicates an exit ates them sequentially in the environment specified by value to the operating system in the same manner as exit. environment-specifier. If environment-specifier is omitted, Note: The emergency-exit procedure corresponds to the (interaction-environment) is assumed. exit procedure in Windows and Posix. 60 Revised7 Scheme

(get-environment-variable name) force many implementations to return integers which must be process-context library procedure allocated for most calls, rendering current-jiffy less useful for Many operating systems provide each running process with accurate timing measurements. an environment consisting of environment variables. (This environment is not to be confused with the Scheme envi- (jiffies-per-second) time library procedure ronments that can be passed to eval: see section 6.12.) Returns an exact integer representing the number of jiffies Both the name and value of an environment variable are per SI second. This value is an implementation-specified strings. The procedure get-environment-variable re- constant. turns the value of the environment variable name, or #f if the named environment variable is not found. It may (define (time-length) use locale information to encode the name and decode the (let ((list (make-list 100000)) value of the environment variable. It is an error if (start (current-jiffy))) get-environment-variable can’t decode the value. It is (length list) also an error to mutate the resulting string. (/ (- (current-jiffy) start) (jiffies-per-second)))) (get-environment-variable "PATH") =⇒ "/usr/local/bin:/usr/bin:/bin" (features) procedure (get-environment-variables) Returns a list of the feature identifiers which cond-expand process-context library procedure treats as true. It is an error to modify this list. Here is an example of what features might return: Returns the names and values of all the environment vari- ables as an alist, where the car of each entry is the name (features) =⇒ of an environment variable and the cdr is its value, both as (r7rs ratios exact-complex full-unicode strings. The order of the list is unspecified. It is an error -linux little-endian to mutate any of these strings or the alist itself. fantastic-scheme fantastic-scheme-1.0 (get-environment-variables) space-ship-control-system) =⇒ (("USER" . "root") ("HOME" . "/"))

(current-second) time library procedure Returns an inexact number representing the current time on the International Atomic Time (TAI) scale. The value 0.0 represents midnight on January 1, 1970 TAI (equiva- lent to ten seconds before midnight Universal Time) and the value 1.0 represents one TAI second later. Neither high accuracy nor high precision are required; in particu- lar, returning Coordinated Universal Time plus a suitable constant might be the best an implementation can do.

(current-jiffy) time library procedure Returns the number of jiffies as an exact integer that have elapsed since an arbitrary, implementation-defined epoch. A jiffy is an implementation-defined fraction of a second which is defined by the return value of the jiffies-per-second procedure. The starting epoch is guaranteed to be constant during a run of the program, but may vary between runs. Rationale: Jiffies are allowed to be implementation-dependent so that current-jiffy can execute with minimum overhead. It should be very likely that a compactly represented integer will suffice as the returned value. Any particular jiffy size will be inappropriate for some implementations: a microsecond is too long for a very fast machine, while a much smaller unit would 7. Formal syntax and semantics 61

7. Formal syntax and semantics htokeni −→ hidentifieri | hbooleani | hnumberi This chapter provides formal descriptions of what has al- | hcharacteri | hstringi ready been described informally in previous chapters of this | ( | ) | #( | #u8( | ’ | ` | , | ,@ | . report. hdelimiteri −→ hwhitespacei | hvertical linei | ( | ) | " | ; hintraline whitespacei −→ hspace or tabi 7.1. Formal syntax hwhitespacei −→ hintraline whitespacei | hline endingi hvertical linei −→ | This section provides a formal syntax for Scheme written hline endingi −→ hnewlinei | hreturni hnewlinei in an extended BNF. | hreturni All spaces in the grammar are for legibility. Case is hcommenti −→ ; hall subsequent characters up to a not significant except in the definitions of hletteri and line endingi hcharacter namei; for example, #x1A and #X1a are equiva- | hnested commenti lent, but foo and Foo and #\space and #\Space are dis- | #; hintertoken spacei hdatumi tinct. hemptyi stands for the empty string. hnested commenti −→ #| hcomment texti hcomment conti* |# The following extensions to BNF are used to make the de- hcomment texti −→ hcharacter sequence not containing scription more concise: hthingi* means zero or more occur- #| or |#i + rences of hthingi; and hthingi means at least one hthingi. hcomment conti −→ hnested commenti hcomment texti hdirectivei −→ #!fold-case | #!no-fold-case 7.1.1. Lexical structure Note that each hdirectivei must be followed by a hdelimiteri This section describes how individual tokens (identifiers, or the end of file. numbers, etc.) are formed from sequences of characters. hatmospherei −→ hwhitespacei | hcommenti | hdirectivei The following sections describe how expressions and pro- hintertoken spacei −→ hatmospherei* grams are formed from sequences of tokens. hIntertoken spacei may occur on either side of any token, Note that +i, -i and hinfnani below are exceptions to the but not within a token. hpeculiar identifieri rule; they are parsed as numbers, not identifiers. Identifiers that do not begin with a vertical line are termi- nated by a hdelimiteri or by the end of the input. So are hidentifieri −→ hinitiali hsubsequenti* dot, numbers, characters, and booleans. Identifiers that | hvertical linei hsymbol elementi* hvertical linei begin with a vertical line are terminated by another verti- | hpeculiar identifieri cal line. hinitiali −→ hletteri | hspecial initiali The following four characters from the ASCII repertoire | hinline hex escapei are reserved for future extensions to the language: []{ hletteri −→ a | b | c | ... | z } | A | B | C | ... | Z hspecial initiali −→ ! | $ | % | & | * | / | : | < | = In addition to the identifier characters of the ASCII reper- | > | ? | ^ | _ | ~ toire specified below, Scheme implementations may permit hsubsequenti −→ hinitiali | hdigiti any additional repertoire of Unicode characters to be em- | hspecial subsequenti ployed in identifiers, provided that each such character has hdigiti −→ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 a Unicode general category of Lu, Ll, Lt, Lm, Lo, Mn, hhex digiti −→ hdigiti | a | b | c | d | e | f Mc, Me, Nd, Nl, No, Pd, Pc, Po, Sc, Sm, Sk, So, or Co, hexplicit signi −→ + | - or is U+200C or U+200D (the zero-width non-joiner and hspecial subsequenti −→ hexplicit signi | . | @ joiner, respectively, which are needed for correct spelling hinline hex escapei −→ \xhhex scalar valuei; in Persian, Hindi, and other languages). However, it is an hhex scalar valuei −→ hhex digiti+ error for the first character to have a general category of hpeculiar identifieri −→ hexplicit signi Nd, Mc, or Me. It is also an error to use a non-Unicode | hexplicit signi hsign subsequenti hsubsequenti* character in symbols or identifiers. | hexplicit signi . hdot subsequenti hsubsequenti* All Scheme implementations must permit the escape se- | . hdot subsequenti hsubsequenti* quence \x; to appear in Scheme identifiers hdot subsequenti −→ hsign subsequenti | . that are enclosed in vertical lines. If the character with the hsign subsequenti −→ hinitiali | hexplicit signi | @ given Unicode scalar value is supported by the implemen- hsymbol elementi −→ tation, identifiers containing such a sequence are equivalent hany character other than hvertical linei or \i to identifiers containing the corresponding character. | hstring elementi | " | \| 62 Revised7 Scheme

hradix 8i −→ #o hbooleani −→ #t | #f | #true | #false hradix 10i −→ hemptyi | #d hradix 16i −→ #x hcharacteri −→ #\ hany characteri hdigit 2i −→ 0 | 1 | #\ hcharacter namei hdigit 8i −→ 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | #\xhhex scalar valuei hdigit 10i −→ hdigiti hcharacter namei −→ alarm | backspace | delete hdigit 16i −→ hdigit 10i | a | b | c | d | e | f | escape | newline | null | return | space | tab hstringi −→ " hstring elementi* " 7.1.2. External representations hstring elementi −→ hany character other than " or \i hDatumi is what the read procedure (section 6.13.2) suc- | \a | \b | \t | \n | \r | \" | \\ cessfully parses. Note that any string that parses as an | \hintraline whitespacei*hline endingi hexpressioni will also parse as a hdatumi. hintraline whitespacei* | hinline hex escapei hdatumi −→ hsimple datumi | hcompound datumi hbytevectori −→ #u8(hbytei*) | hlabeli = hdatumi | hlabeli # hbytei −→ hany exact integer between 0 and 255i hsimple datumi −→ hbooleani | hnumberi | hcharacteri | hstringi | hsymboli | hbytevectori hnumberi −→ hnum 2i | hnum 8i hsymboli −→ hidentifieri | hnum 10i | hnum 16i hcompound datumi −→ hlisti | hvectori | habbreviationi hlisti −→ (hdatumi*) | (hdatumi+ . hdatumi) The following rules for hnum Ri, hcomplex Ri, hreal Ri, habbreviationi −→ habbrev prefixi hdatumi hureal Ri, huinteger Ri, and hprefix Ri are implicitly repli- habbrev prefixi −→ ’ | ` | , | ,@ cated for R = 2, 8, 10, and 16. There are no rules for hvectori −→ #(hdatumi*) hdecimal 2i, hdecimal 8i, and hdecimal 16i, which means hlabeli −→ # hdigit 10i+ that numbers containing decimal points or exponents are always in decimal radix. Although not shown below, all al- 7.1.3. Expressions phabetic characters used in the grammar of numbers may appear in either upper or lower case. The definitions in this and the following subsections assume hnum Ri −→ hprefix Ri hcomplex Ri that all the syntax keywords defined in this report have hcomplex Ri −→ hreal Ri | hreal Ri @ hreal Ri been properly imported from their libraries, and that none | hreal Ri + hureal Ri i | hreal Ri - hureal Ri i of them have been redefined or shadowed. | hreal Ri + i | hreal Ri - i | hreal Ri hinfnani i | + hureal Ri i | - hureal Ri i hexpressioni −→ hidentifieri | hinfnani i | + i | - i | hliterali hreal Ri −→ hsigni hureal Ri | hprocedure calli | hinfnani | hlambda expressioni hureal Ri −→ huinteger Ri | hconditionali | huinteger Ri / huinteger Ri | hassignmenti | hdecimal Ri | hderived expressioni hdecimal 10i −→ huinteger 10i hsuffixi | hmacro usei | . hdigit 10i+ hsuffixi | hmacro blocki | hdigit 10i+ . hdigit 10i* hsuffixi | hincluderi huinteger Ri −→ hdigit Ri+ hprefix Ri −→ hradix Ri hexactnessi hliterali −→ hquotationi | hself-evaluatingi | hexactnessi hradix Ri hself-evaluatingi −→ hbooleani | hnumberi | hvectori hinfnani −→ +inf.0 | -inf.0 | +nan.0 | -nan.0 | hcharacteri | hstringi | hbytevectori hquotationi −→ ’hdatumi | (quote hdatumi) hprocedure calli −→ (hoperatori hoperandi*) hsuffixi −→ hemptyi hoperatori −→ hexpressioni | hexponent markeri hsigni hdigit 10i+ hoperandi −→ hexpressioni hexponent markeri −→ e | s | f | d | l hsigni −→ hemptyi | + | - hlambda expressioni −→ (lambda hformalsi hbodyi) hexactnessi −→ hemptyi | #i | #e hformalsi −→ (hidentifieri*) | hidentifieri hradix 2i −→ #b | (hidentifieri+ . hidentifieri) 7. Formal syntax and semantics 63 hbodyi −→ hdefinitioni* hsequencei hcase-lambda clausei −→ (hformalsi hbodyi) hsequencei −→ hcommandi* hexpressioni hiniti −→ hexpressioni hcommandi −→ hexpressioni hstepi −→ hexpressioni hdo resulti −→ hsequencei | hemptyi hconditionali −→ (if htesti hconsequenti halternatei) htesti −→ hexpressioni hmacro usei −→ (hkeywordi hdatumi*) hconsequenti −→ hexpressioni hkeywordi −→ hidentifieri halternatei −→ hexpressioni | hemptyi hmacro blocki −→ hassignmenti −→ (set! hidentifieri hexpressioni) (let-syntax (hsyntax speci*) hbodyi) | (letrec-syntax (hsyntax speci*) hbodyi) hderived expressioni −→ hsyntax speci −→ (hkeywordi htransformer speci) (cond hcond clausei+) | (cond hcond clausei* (else hsequencei)) hincluderi −→ | (case hexpressioni | (include hstringi+) hcase clausei+) | (include-ci hstringi+) | (case hexpressioni hcase clausei* (else hsequencei)) | (case hexpressioni 7.1.4. Quasiquotations hcase clausei* The following grammar for quasiquote expressions is not (else => hrecipienti)) context-free. It is presented as a recipe for generating an | (and htesti*) infinite number of production rules. Imagine a copy of the | (or htesti*) following rules for D = 1, 2, 3,..., where D is the nesting | (when htesti hsequencei) depth. | (unless htesti hsequencei) | (let (hbinding speci*) hbodyi) hquasiquotationi −→ hquasiquotation 1i | (let hidentifieri (hbinding speci*) hbodyi) hqq template 0i −→ hexpressioni | (let* (hbinding speci*) hbodyi) hquasiquotation Di −→ `hqq template Di | (letrec (hbinding speci*) hbodyi) | (quasiquote hqq template Di) | (letrec* (hbinding speci*) hbodyi) hqq template Di −→ hsimple datumi | (let-values (hmv binding speci*) hbodyi) | hlist qq template Di | (let*-values (hmv binding speci*) hbodyi) | hvector qq template Di | (begin hsequencei) | hunquotation Di | (do (hiteration speci*) hlist qq template Di −→ (hqq template or splice Di*) (htesti hdo resulti) | (hqq template or splice Di+ . hqq template Di) hcommandi*) | ’hqq template Di | (delay hexpressioni) | hquasiquotation D + 1i | (delay-force hexpressioni) hvector qq template Di −→ #(hqq template or splice Di*) | (parameterize ((hexpressioni hexpressioni)*) hunquotation Di −→ ,hqq template D − 1i hbodyi) | (unquote hqq template D − 1i) | (guard (hidentifieri hcond clausei*) hbodyi) hqq template or splice Di −→ hqq template Di | hquasiquotationi | hsplicing unquotation Di | (case-lambda hcase-lambda clausei*) hsplicing unquotation Di −→ ,@hqq template D − 1i | (unquote-splicing hqq template D − 1i) hcond clausei −→ (htesti hsequencei) | (htesti) In hquasiquotationis, a hlist qq template Di can some- | (htesti => hrecipienti) times be confused with either an hunquotation Di or hrecipienti −→ hexpressioni a hsplicing unquotation Di. The interpretation as an hcase clausei −→ ((hdatumi*) hsequencei) hunquotationi or hsplicing unquotation Di takes prece- | ((hdatumi*) => hrecipienti) dence. hbinding speci −→ (hidentifieri hexpressioni) hmv binding speci −→ (hformalsi hexpressioni) 7.1.5. Transformers hiteration speci −→ (hidentifieri hiniti hstepi) | hidentifieri hiniti ( ) htransformer speci −→ 64 Revised7 Scheme

(syntax-rules (hidentifieri*) hsyntax rulei*) (define-syntax hkeywordi htransformer speci) | (syntax-rules hidentifieri (hidentifieri*) hsyntax rulei*) hsyntax rulei −→ (hpatterni htemplatei) hpatterni −→ hpattern identifieri 7.1.7. Libraries | hunderscorei hlibraryi −→ | (hpatterni*) (define-library hlibrary namei | (hpatterni+ . hpatterni) hlibrary declarationi*) | (hpatterni* hpatterni hellipsisi hpatterni*) hlibrary namei −→ (hlibrary name parti+) | (hpatterni* hpatterni hellipsisi hpatterni* hlibrary name parti −→ hidentifieri | huinteger 10i . hpatterni) hlibrary declarationi −→ (export hexport speci*) | #(hpatterni*) | himport declarationi | #(hpatterni* hpatterni hellipsisi hpatterni*) | (begin hlibrary declarationi*) | hpattern datumi | hincluderi hpattern datumi −→ hstringi | (cond-expand hcond-expand clausei+) | hcharacteri | (cond-expand hcond-expand clausei+ | hbooleani (else hlibrary declarationi*)) | hnumberi himport declarationi −→ (import himport seti+) htemplatei −→ hpattern identifieri hexport speci −→ hidentifieri | (htemplate elementi*) | (rename hidentifieri hidentifieri) | (htemplate elementi+ . htemplatei) himport seti −→ hlibrary namei | #(htemplate elementi*) | (only himport seti hidentifieri+) | htemplate datumi | (except himport seti hidentifieri+) htemplate elementi −→ htemplatei | (prefix himport seti hidentifieri) | htemplatei hellipsisi | (rename himport seti (hidentifieri hidentifieri)+) htemplate datumi −→ hpattern datumi hcond-expand clausei −→ hpattern identifieri −→ hany identifier except ...i (hfeature requirementi hlibrary declarationi*) hellipsisi −→ han identifier defaulting to ...i hfeature requirementi −→ hidentifieri hunderscorei −→ hthe identifier i | hlibrary namei | (and hfeature requirementi*) | (or hfeature requirementi*) 7.1.6. Programs and definitions | (not hfeature requirementi) hprogrami −→ himport declarationi+ hcommand or definitioni+ 7.2. Formal semantics hcommand or definitioni −→ hcommandi | hdefinitioni This section provides a formal denotational semantics for | (begin hcommand or definitioni+) the primitive expressions of Scheme and selected built-in hdefinitioni −→ (define hidentifieri hexpressioni) procedures. The concepts and notation used here are de- | (define (hidentifieri hdef formalsi) hbodyi) scribed in [37]; the definition of dynamic-wind is taken | hsyntax definitioni from [40]. The notation is summarized below: | (define-values hdef formalsi hbodyi) h ... i sequence formation | (define-record-type hidentifieri s ↓ k kth member of the sequence s (1-based) hconstructori hidentifieri hfield speci*) #s length of sequence s | (begin hdefinitioni*) hdef formalsi −→ hidentifieri* s § t concatenation of sequences s and t s † k drop the first k members of sequence s | hidentifieri* . hidentifieri t → a, b McCarthy conditional “if t then a else b” hconstructori −→ (hidentifieri hfield namei*) ρ[x/i] substitution “ρ with x for i” hfield speci −→ (hfield namei haccessori) x in injection of x into domain | (hfield namei haccessori hmutatori) D D hfield namei −→ hidentifieri x | D projection of x to domain D haccessori −→ hidentifieri The reason that expression continuations take sequences hmutatori −→ hidentifieri of values instead of single values is to simplify the formal hsyntax definitioni −→ treatment of procedure calls and multiple return values. 7. Formal syntax and semantics 65

The boolean flag associated with pairs, vectors, and strings 7.2.2. Domain equations will be true for mutable objects and false for immutable objects. α ∈ L locations ν ∈ N natural numbers T = {false, true} booleans The order of evaluation within a call is unspecified. We Q symbols mimic that here by applying arbitrary permutations per- H characters mute and unpermute, which must be inverses, to the argu- R numbers ments in a call before and after they are evaluated. This is E = L × L × T pairs not quite right since it suggests, incorrectly, that the order p E = L* × T vectors of evaluation is constant throughout a program (for any v E = L* × T strings given number of arguments), but it is a closer approxima- s M = {false, true, null, undefined, unspecified} tion to the intended semantics than a left-to-right evalua- miscellaneous tion would be. φ ∈ F = L × (E* → P → K → C) procedure values  ∈ E = Q + H + R + Ep + Ev + Es + M + F The storage allocator new is implementation-dependent, expressed values but it must obey the following axiom: if new σ ∈ , then L σ ∈ S = L → (E × T) stores σ (new σ | ) ↓ 2 = false. L ρ ∈ U = Ide → L environments θ ∈ C = S → A command conts The definition of K is omitted because an accurate defini- κ ∈ K = E* → C expression conts tion of K would complicate the semantics without being A answers very interesting. X errors ω ∈ P = (F × F × P) + {root} dynamic points If P is a program in which all variables are defined before being referenced or assigned, then the meaning of P is 7.2.3. Semantic functions K : Con → E E[[ I* P hundefinedi ... ]] ((lambda ( ) ’) ) E : Exp → U → P → K → C E* : Exp* → U → P → K → C where I* is the sequence of variables defined in P, P0 is the C : Com* → U → P → C → C sequence of expressions obtained by replacing every defini- Definition of K deliberately omitted. tion in P by an assignment, hundefinedi is an expression that evaluates to undefined, and E is the semantic function E[[K]] = λρωκ . send (K[[K]]) κ that assigns meaning to expressions. E[[I]] = λρωκ . hold (lookup ρ I) (single(λ .  = undefined → wrong “undefined variable”, send  κ)) E[[ E E* ]] = 7.2.1. Abstract syntax ( 0 ) λρωκ . E*(permute(hE0i § E*)) ρ ω K ∈ Con constants, including quotations (λ* . ((λ* . applicate (* ↓ 1) (* † 1) ωκ) I ∈ Ide identifiers (variables) (unpermute *))) E ∈ Exp expressions Γ ∈ Com = Exp commands E[[(lambda (I*) Γ* E0)]] = λρωκ . λσ . new σ ∈ L → send (hnew σ | L, λ*ω0κ0 . #* = #I* → 0 0 0 0 0 0 Exp −→ K | I | (E0 E*) tievals(λα* . (λρ . C[[Γ*]]ρ ω (E[[E0]]ρ ω κ )) (extends ρ I* α*)) | (lambda (I*) Γ* E0) *, | (lambda (I* . I) Γ* E0) wrong “wrong number of arguments”i | (lambda I Γ* E0) in E) | (if E E E ) | (if E E ) 0 1 2 0 1 κ | IE (set! ) (update (new σ | L) unspecified σ), wrong “out of memory” σ 66 Revised7 Scheme

E[[(lambda (I* . I) Γ* E0)]] = assign : L → E → C → C λρωκ . λσ . assign = λαθσ . θ(update ασ) new σ ∈ L → send (hnew σ | L, update : L → E → S → S λ*ω0κ0 . #* ≥ #I* → update = λασ . σ[h, truei/α] tievalsrest tievals :(L* → C) → E* → C 0 0 0 0 0 0 (λα* . (λρ . C[[Γ*]]ρ ω (E[[E0]]ρ ω κ )) tievals = (extends ρ (I* § hIi) α*)) λψ*σ . #* = 0 → ψh iσ, * new σ ∈ L → tievals (λα* . ψ(hnew σ | Li § α*)) (#I*), (* † 1) wrong “too few arguments”i in E) (update(new σ | L)(* ↓ 1)σ), κ wrong “out of memory”σ (update (new σ | L) unspecified σ), wrong “out of memory” σ tievalsrest :(L* → C) → E* → N → C tievalsrest = E[[(lambda I Γ* E0)]] = E[[(lambda (. I) Γ* E0)]] λψ*ν . list (dropfirst *ν) (single(λ . tievals ψ ((takefirst *ν) § hi))) E[[(if E0 E1 E2)]] = λρωκ . E[[E0]] ρω (single (λ . truish  → E[[E1]]ρωκ, dropfirst = λln . n = 0 → l, dropfirst (l † 1)(n − 1) E[[E2]]ρωκ)) takefirst = λln . n = 0 → h i, hl ↓ 1i § (takefirst (l † 1)(n − 1)) E[[(if E0 E1)]] = λρωκ . E[[E0]] ρω (single (λ . truish  → E[[E1]]ρωκ, truish : E → T send unspecified κ)) truish = λ .  = false → false, true Here and elsewhere, any expressed value other than undefined permute : Exp* → Exp* [implementation-dependent] may be used in place of unspecified. unpermute : E* → E* [inverse of permute] E[[(set! IE)]] = λρωκ . E[[E]] ρ ω (single(λ . assign (lookup ρ I) applicate : E → E* → P → K → C  applicate = (send unspecified κ))) λ*ωκ .  ∈ F → ( | F ↓ 2)*ωκ, wrong “bad procedure” E*[[]] = λρωκ . κh i onearg :(E → P → K → C) → (E* → P → K → C) onearg = E*[[E0 E*]] = λζ*ωκ . #* = 1 → ζ(* ↓ 1)ωκ, λρωκ . E[[E0]] ρω (single(λ0 . E*[[E*]] ρω (λ* . κ (h0i § *)))) wrong “wrong number of arguments”

C[[]] = λρωθ . θ twoarg :(E → E → P → K → C) → (E* → P → K → C) twoarg = C[[Γ0 Γ*]] = λρωθ . E[[Γ0]] ρω (λ* . C[[Γ*]]ρωθ) λζ*ωκ . #* = 2 → ζ(* ↓ 1)(* ↓ 2)ωκ, wrong “wrong number of arguments” 7.2.4. Auxiliary functions threearg :(E → E → E → P → K → C) → (E* → P → K → C) lookup : U → Ide → L threearg = lookup = λρI . ρI λζ*ωκ . #* = 3 → ζ(* ↓ 1)(* ↓ 2)(* ↓ 3)ωκ, wrong “wrong number of arguments” extends : U → Ide* → L* → U extends = list : E* → P → K → C λρI*α* . #I* = 0 → ρ, list = extends (ρ[(α* ↓ 1)/(I* ↓ 1)]) (I* † 1) (α* † 1) λ*ωκ . #* = 0 → send null κ, list (* † 1)(single(λ . consh* ↓ 1, iκ)) wrong : X → C [implementation-dependent] cons : E* → P → K → C send : E → K → C cons = send = λκ . κhi twoarg (λ12κωσ . new σ ∈ L → 0 0 single :( → ) → (λσ . new σ ∈ L → E C K 0 single = send (hnew σ | L, new σ | L, truei λψ* . #* = 1 → ψ(* ↓ 1), in E) wrong “wrong number of return values” κ 0 0 (update(new σ | L)2σ ), new : S → (L + {error}) [implementation-dependent] wrong “out of memory”σ0) (update(new σ | L) σ), hold : L → K → C 1 wrong “out of memory”σ) hold = λακσ . send (σα ↓ 1)κσ 7. Formal syntax and semantics 67 less : E* → P → K → C valueslist : E → K → C less = valueslist = twoarg (λ12ωκ . (1 ∈ R ∧ 2 ∈ R) → λκ .  ∈ Ep → send (1 | R < 2 | R → true, false)κ, cdr-internal  wrong “non-numeric argument to <”) (λ* . valueslist * add : E* → P → K → C (λ* . car-internal add =  twoarg (λ12ωκ . (1 ∈ R ∧ 2 ∈ R) → (single(λ . κ(hi § *))))), send ((1 | R + 2 | R) in E)κ,  = null → κh i, wrong “non-numeric argument to +”) wrong “non-list argument to values-list” car : E* → P → K → C cwcc: E* → P → K → C car = [call-with-current-continuation] onearg (λωκ .  ∈ Ep → car-internal κ, cwcc = wrong “non-pair argument to car”) onearg (λωκ .  ∈ F → (λσ . new σ ∈ L → car-internal : E → K → C applicate  car-internal = λωκ . hold ( | Ep ↓ 1)κ hhnew σ | L, λ*ω0κ0 . travel ω0ω(κ*)i cdr : E* → P → K → C [similar to car] in Ei ω cdr-internal : → → [similar to car-internal] E K C κ (update (new σ | L) setcar : E* → P → K → C unspecified setcar = σ), twoarg (λ  ωκ .  ∈ E → 1 2 1 p wrong “out of memory” σ), ( | E ↓ 3) → assign ( | E ↓ 1) 1 p 1 p wrong “bad procedure argument”) 2 (send unspecified κ), travel : P → P → C → C wrong “immutable argument to set-car!”, travel = wrong “non-pair argument to set-car!”) λω1ω2 . travelpath ((pathup ω1(commonancest ω1ω2)) § (pathdown (commonancest ω1ω2)ω2)) eqv : E* → P → K → C eqv = pointdepth : P → N twoarg (λ12ωκ . (1 ∈ M ∧ 2 ∈ M) → pointdepth = send (1 | M = 2 | M → true, false)κ, λω . ω = root → 0, 1 + (pointdepth (ω | (F × F × P) ↓ 3)) ( ∈ Q ∧  ∈ Q) → 1 2 ancestors : P → PP send ( | Q =  | Q → true, false)κ, 1 2 ancestors = ( ∈ H ∧  ∈ H) → 1 2 λω . ω = root → {ω}, {ω} ∪ (ancestors (ω | (F × F × P) ↓ 3)) send (1 | H = 2 | H → true, false)κ, (1 ∈ R ∧ 2 ∈ R) → commonancest : P → P → P send (1 | R = 2 | R → true, false)κ, commonancest = ∈ ∈ (1 Ep ∧ 2 Ep) → λω1ω2 . the only element of 0 0 send ((λp1p2 . ((p1 ↓ 1) = (p2 ↓ 1)∧ {ω | ω ∈ (ancestors ω1) ∩ (ancestors ω2), (p1 ↓ 2) = (p2 ↓ 2)) → true, pointdepth ω0 ≥ pointdepth ω00 00 false) ∀ω ∈ (ancestors ω1) ∩ (ancestors ω2)} (1 | Ep) (2 | Ep)) pathup : P → P → (P × F)* κ, pathup = (1 ∈ Ev ∧ 2 ∈ Ev) → ..., λω1ω2 . ω1 = ω2 → hi, (1 ∈ Es ∧ 2 ∈ Es) → ..., h(ω1, ω1 | (F × F × P) ↓ 2)i § (1 ∈ F ∧ 2 ∈ F) → (pathup (ω1 | (F × F × P) ↓ 3)ω2) send (( | F ↓ 1) = ( | F ↓ 1) → true, false) 1 2 pathdown : → → ( × )* κ, P P P F pathdown = send false κ) λω1ω2 . ω1 = ω2 → hi, apply : E* → P → K → C (pathdown ω1(ω2 | (F × F × P) ↓ 3)) § apply = h(ω2, ω2 | (F × F × P) ↓ 1)i twoarg (λ12ωκ . 1 ∈ F → valueslist 2(λ* . applicate 1*ωκ), travelpath :(P × F)* → C → C wrong “bad procedure argument to apply”) travelpath = 68 Revised7 Scheme

λπ*θ . #π* = 0 → θ, ((case key ((π* ↓ 1) ↓ 2)hi((π* ↓ 1) ↓ 1) (else => result)) (λ* . travelpath (π* † 1)θ) (result key)) ((case key dynamicwind : E* → P → K → C (else result1 result2 ...)) dynamicwind = (begin result1 result2 ...)) threearg (λ123ωκ . (1 ∈ F ∧ 2 ∈ F ∧ 3 ∈ F) → ((case key applicate 1hiω(λζ* . ((atoms ...) result1 result2 ...)) applicate 2hi((1 | F, 3 | F, ω) in P) (if (memv key ’(atoms ...)) (λ* . applicate 3hiω(λζ* . κ*))), (begin result1 result2 ...))) wrong “bad procedure argument”) ((case key values : E* → P → K → C ((atoms ...) => result)) values = λ*ωκ . κ* (if (memv key ’(atoms ...)) (result key))) cwv : E* → P → K → C [call-with-values] ((case key cwv = ((atoms ...) => result) twoarg (λ12ωκ . applicate 1h iω(λ* . applicate 2 *ω)) clause clauses ...) (if (memv key ’(atoms ...)) (result key) 7.3. Derived expression types (case key clause clauses ...))) ((case key This section gives syntax definitions for the derived ex- ((atoms ...) result1 result2 ...) pression types in terms of the primitive expression types clause clauses ...) (literal, variable, call, lambda, if, and set!), except for (if (memv key ’(atoms ...)) (begin result1 result2 ...) quasiquote. (case key clause clauses ...))))) Conditional derived syntax types: (define-syntax cond (define-syntax and (syntax-rules (else =>) (syntax-rules () ((cond (else result1 result2 ...)) ((and) #t) (begin result1 result2 ...)) ((and test) test) ((cond (test => result)) ((and test1 test2 ...) (let ((temp test)) (if test1 (and test2 ...) #f)))) (if temp (result temp)))) ((cond (test => result) clause1 clause2 ...) (let ((temp test)) (define-syntax or (if temp (syntax-rules () (result temp) ((or) #f) (cond clause1 clause2 ...)))) ((or test) test) ((cond (test)) test) ((or test1 test2 ...) ((cond (test) clause1 clause2 ...) (let ((x test1)) (let ((temp test)) (if x x (or test2 ...)))))) (if temp temp (define-syntax when (cond clause1 clause2 ...)))) (syntax-rules () ((cond (test result1 result2 ...)) ((when test result1 result2 ...) (if test (begin result1 result2 ...))) (if test ((cond (test result1 result2 ...) (begin result1 result2 ...))))) clause1 clause2 ...) (if test (begin result1 result2 ...) (define-syntax unless (cond clause1 clause2 ...))))) (syntax-rules () ((unless test result1 result2 ...) (if (not test) (define-syntax case (begin result1 result2 ...))))) (syntax-rules (else =>) ((case (key ...) clauses ...) Binding constructs: (let ((atom-key (key ...))) (case atom-key clauses ...))) (define-syntax let 7. Formal syntax and semantics 69

(syntax-rules () (define-syntax letrec* ((let ((name val) ...) body1 body2 ...) (syntax-rules () ((lambda (name ...) body1 body2 ...) ((letrec* ((var1 init1) ...) body1 body2 ...) val ...)) (let ((var1 ) ...) ((let tag ((name val) ...) body1 body2 ...) (set! var1 init1) ((letrec ((tag (lambda (name ...) ... body1 body2 ...))) (let () body1 body2 ...))))) tag) val ...)))) (define-syntax let-values (syntax-rules () ((let-values (binding ...) body0 body1 ...) (define-syntax let* (let-values "bind" (syntax-rules () (binding ...) () (begin body0 body1 ...))) ((let* () body1 body2 ...) (let () body1 body2 ...)) ((let-values "bind" () tmps body) ((let* ((name1 val1) (name2 val2) ...) (let tmps body)) body1 body2 ...) (let ((name1 val1)) ((let-values "bind" ((b0 e0) (let* ((name2 val2) ...) binding ...) tmps body) body1 body2 ...))))) (let-values "mktmp" b0 e0 () (binding ...) tmps body))

The following letrec macro uses the symbol ((let-values "mktmp" () e0 args in place of an expression which returns something that bindings tmps body) when stored in a location makes it an error to try to obtain (call-with-values the value stored in the location. (No such expression is de- (lambda () e0) fined in Scheme.) A trick is used to generate the temporary (lambda args names needed to avoid specifying the order in which the (let-values "bind" values are evaluated. This could also be accomplished by bindings tmps body)))) using an auxiliary macro. ((let-values "mktmp" (a . b) e0 (arg ...) (define-syntax letrec bindings (tmp ...) body) (syntax-rules () (let-values "mktmp" b e0 (arg ... x) ((letrec ((var1 init1) ...) body ...) bindings (tmp ... (a x)) body)) (letrec "generate temp names" (var1 ...) ((let-values "mktmp" a e0 (arg ...) () bindings (tmp ...) body) ((var1 init1) ...) (call-with-values body ...)) (lambda () e0) ((letrec "generate temp names" (lambda (arg ... . x) () (let-values "bind" (temp1 ...) bindings (tmp ... (a x)) body)))))) ((var1 init1) ...) body ...) (define-syntax let*-values (let ((var1 ) ...) (syntax-rules () (let ((temp1 init1) ...) ((let*-values () body0 body1 ...) (set! var1 temp1) (let () body0 body1 ...)) ... body ...))) ((let*-values (binding0 binding1 ...) ((letrec "generate temp names" body0 body1 ...) (x y ...) (let-values (binding0) (temp ...) (let*-values (binding1 ...) ((var1 init1) ...) body0 body1 ...))))) body ...) (letrec "generate temp names" (y ...) (define-syntax define-values (newtemp temp ...) (syntax-rules () ((var1 init1) ...) ((define-values () expr) body ...)))) (define dummy (call-with-values (lambda () expr) 70 Revised7 Scheme

(lambda args #f)))) (define-syntax do ((define-values (var) expr) (syntax-rules () (define var expr)) ((do ((var init step ...) ...) ((define-values (var0 var1 ... varn) expr) (test expr ...) (begin command ...) (define var0 (letrec (call-with-values (lambda () expr) ((loop list)) (lambda (var ...) (define var1 (if test (let ((v (cadr var0))) (begin (set-cdr! var0 (cddr var0)) (if #f #f) v)) ... expr ...) (define varn (begin (let ((v (cadr var0))) command (set! var0 (car var0)) ... v)))) (loop (do "step" var step ...) ((define-values (var0 var1 ... . varn) expr) ...)))))) (begin (loop init ...))) (define var0 ((do "step" x) (call-with-values (lambda () expr) x) list)) ((do "step" x y) (define var1 y))) (let ((v (cadr var0))) (set-cdr! var0 (cddr var0)) v)) ... Here is a possible implementation of delay, force and (define varn delay-force. We define the expression (let ((v (cdr var0))) (delay-force hexpressioni) (set! var0 (car var0)) v)))) to have the same meaning as the procedure call ((define-values var expr) (define var (make-promise #f (lambda () hexpressioni)) (call-with-values (lambda () expr) as follows list))))) (define-syntax delay-force (define-syntax begin (syntax-rules () (syntax-rules () ((delay-force expression) ((begin exp ...) (make-promise #f (lambda () expression))))) ((lambda () exp ...))))) and we define the expression hexpressioni The following alternative expansion for begin does not (delay ) make use of the ability to write more than one expression to have the same meaning as: in the body of a lambda expression. In any case, note that these rules apply only if the body of the begin contains no (delay-force (make-promise #t hexpressioni)) definitions. as follows (define-syntax begin (define-syntax delay (syntax-rules () (syntax-rules () ((begin exp) ((delay expression) exp) (delay-force (make-promise #t expression))))) ((begin exp1 exp2 ...) (call-with-values where make-promise is defined as follows: (lambda () exp1) (lambda args (define make-promise (begin exp2 ...)))))) (lambda (done? proc) (list (cons done? proc)))) The following syntax definition of do uses a trick to expand Finally, we define force to call the procedure expressions the variable clauses. As with letrec above, an auxiliary in promises iteratively using a trampoline technique fol- macro would also work. The expression (if #f #f) is used lowing [39] until a non-lazy result (i.e. a value created by to obtain an unspecific value. delay instead of delay-force) is returned, as follows: 7. Formal syntax and semantics 71

(define (force promise) ((param value p old new) . args) (if (promise-done? promise) rest (promise-value promise) body)) (let ((promise* ((promise-value promise)))) ((parameterize ((param value) ...) . body) (unless (promise-done? promise) (parameterize ("step") (promise-update! promise* promise)) () (force promise)))) ((param value) ...) body)))) with the following promise accessors:

(define promise-done? The following implementation of guard depends on an aux- (lambda (x) (car (car x)))) iliary macro, here called guard-aux. (define promise-value (lambda (x) (cdr (car x)))) (define-syntax guard (define promise-update! (syntax-rules () (lambda (new old) ((guard (var clause ...) e1 e2 ...) (set-car! (car old) (promise-done? new)) ((call/cc (set-cdr! (car old) (promise-value new)) (lambda (guard-k) (set-car! new (car old)))) (with-exception-handler (lambda (condition) The following implementation of make-parameter and ((call/cc parameterize is suitable for an implementation with no (lambda (handler-k) threads. Parameter objects are implemented here as pro- (guard-k cedures, using two arbitrary unique objects (lambda () and : (let ((var condition)) (guard-aux (define (make-parameter init . o) (handler-k (let* ((converter (lambda () (if (pair? o) (car o) (lambda (x) x))) (raise-continuable condition))) (value (converter init))) clause ...)))))))) (lambda args (lambda () (cond (call-with-values ((null? args) (lambda () e1 e2 ...) value) (lambda args ((eq? (car args) ) (guard-k (set! value (cadr args))) (lambda () ((eq? (car args) ) (apply values args))))))))))))) converter) (else (define-syntax guard-aux (error "bad parameter syntax")))))) (syntax-rules (else =>) Then parameterize uses dynamic-wind to dynamically re- ((guard-aux reraise (else result1 result2 ...)) bind the associated value: (begin result1 result2 ...)) ((guard-aux reraise (test => result)) (define-syntax parameterize (let ((temp test)) (syntax-rules () (if temp ((parameterize ("step") (result temp) ((param value p old new) ...) reraise))) () ((guard-aux reraise (test => result) body) clause1 clause2 ...) (let ((p param) ...) (let ((temp test)) (let ((old (p)) ... (if temp (new ((p ) value)) ...) (result temp) (dynamic-wind (guard-aux reraise clause1 clause2 ...)))) (lambda () (p new) ...) ((guard-aux reraise (test)) (lambda () . body) (or test reraise)) (lambda () (p old) ...))))) ((guard-aux reraise (test) clause1 clause2 ...) ((parameterize ("step") (let ((temp test)) args (if temp ((param value) . rest) temp body) (guard-aux reraise clause1 clause2 ...)))) (parameterize ("step") ((guard-aux reraise (test result1 result2 ...)) 72 Revised7 Scheme

(if test ((cond-expand ((or req1 req2 ...) body ...) (begin result1 result2 ...) more-clauses ...) reraise)) (cond-expand ((guard-aux reraise (req1 (test result1 result2 ...) (begin body ...)) clause1 clause2 ...) (else (if test (cond-expand (begin result1 result2 ...) ((or req2 ...) body ...) (guard-aux reraise clause1 clause2 ...))))) more-clauses ...)))) ((cond-expand ((not req) body ...) more-clauses ...) (define-syntax case-lambda (cond-expand (syntax-rules () (req ((case-lambda (params body0 ...) ...) (cond-expand more-clauses ...)) (lambda args (else body ...))) (let ((len (length args))) ((cond-expand (r7rs body ...) (let-syntax more-clauses ...) ((cl (syntax-rules ::: () (begin body ...)) ((cl) ;; Add clauses here for each (error "no matching clause")) ;; supported feature identifier. ((cl ((p :::) . body) . rest) ;; Samples: (if (= len (length ’(p :::))) ;; ((cond-expand (exact-closed body ...) (apply (lambda (p :::) ;; more-clauses ...) . body) ;; (begin body ...)) args) ;; ((cond-expand (ieee-float body ...) (cl . rest))) ;; more-clauses ...) ((cl ((p ::: . tail) . body) ;; (begin body ...)) . rest) ((cond-expand ((library (scheme base)) (if (>= len (length ’(p :::))) body ...) (apply more-clauses ...) (lambda (p ::: . tail) (begin body ...)) . body) ;; Add clauses here for each library args) ((cond-expand (feature-id body ...) (cl . rest)))))) more-clauses ...) (cl (params body0 ...) ...))))))) (cond-expand more-clauses ...)) ((cond-expand ((library (name ...)) body ...) more-clauses ...) This definition of cond-expand does not interact with the (cond-expand more-clauses ...)))) features procedure. It requires that each feature identifier provided by the implementation be explicitly mentioned.

(define-syntax cond-expand ;; Extend this to mention all feature ids and libraries (syntax-rules (and or not else r7rs library scheme base) ((cond-expand) (syntax-error "Unfulfilled cond-expand")) ((cond-expand (else body ...)) (begin body ...)) ((cond-expand ((and) body ...) more-clauses ...) (begin body ...)) ((cond-expand ((and req1 req2 ...) body ...) more-clauses ...) (cond-expand (req1 (cond-expand ((and req2 ...) body ...) more-clauses ...)) more-clauses ...)) ((cond-expand ((or) body ...) more-clauses ...) (cond-expand more-clauses ...)) Appendix A. Standard Libraries 73

Appendix A. Standard Libraries else eof-object eof-object? eq? This section lists the exports provided by the standard li- equal? eqv? braries. The libraries are factored so as to separate features error error-object-irritants which might not be supported by all implementations, or error-object-message error-object? which might be expensive to load. even? exact The scheme library prefix is used for all standard libraries, exact-integer-sqrt exact-integer? and is reserved for use by future standards. exact? expt features file-error? Base Library floor floor-quotient floor-remainder floor/ The (scheme base) library exports many of the proce- flush-output-port for-each dures and syntax bindings that are traditionally associated gcd get-output-bytevector with Scheme. The division between the base library and get-output-string guard the other standard libraries is based on use, not on con- if import struction. In particular, some facilities that are typically include include-ci implemented as primitives by a compiler or the run-time inexact inexact? system rather than in terms of other standard procedures input-port-open? input-port? or syntax are not part of the base library, but are defined in integer->char integer? separate libraries. By the same token, some exports of the lambda lcm base library are implementable in terms of other exports. length let let* let*-values They are redundant in the strict sense of the word, but let-syntax let-values they capture common patterns of usage, and are therefore letrec letrec* provided as convenient abbreviations. letrec-syntax list * + list->string list->vector - ... list-copy list-ref / < list-set! list-tail <= = list? make-bytevector => > make-list make-parameter >= make-string make-vector abs and map max append apply member memq assoc assq memv min assv begin modulo negative? binary-port? boolean=? newline not boolean? bytevector null? number->string bytevector-append bytevector-copy number? numerator bytevector-copy! bytevector-length odd? open-input-bytevector bytevector-u8-ref bytevector-u8-set! open-input-string open-output-bytevector bytevector? caar open-output-string or cadr output-port-open? output-port? call-with-current-continuation pair? parameterize call-with-port call-with-values peek-char peek-u8 call/cc car port? positive? case cdar procedure? quasiquote cddr cdr quote quotient ceiling char->integer raise raise-continuable char-ready? char<=? rational? rationalize char=? char>? read-char read-error? char? close-input-port read-line read-string close-output-port close-port read-u8 real? complex? cond remainder reverse cond-expand cons round set! current-error-port current-input-port set-car! set-cdr! current-output-port define square string define-record-type define-syntax string->list string->number define-values denominator string->symbol string->utf8 do dynamic-wind string->vector string-append 74 Revised7 Scheme

string-copy string-copy! CxR Library string-fill! string-for-each The library exports twenty-four procedures string-length string-map (scheme cxr) string-ref string-set! which are the compositions of from three to four car and string<=? string=? (define caddar string>? string? (lambda (x) (car (cdr (cdr (car x)))))). substring symbol->string symbol=? symbol? The procedures car and cdr themselves and the four two- syntax-error syntax-rules level compositions are included in the base library. See textual-port? truncate section 6.4. truncate-quotient truncate-remainder truncate/ u8-ready? caaaar caaadr unless unquote caaar caadar unquote-splicing utf8->string caaddr caadr values vector cadaar cadadr vector->list vector->string cadar caddar vector-append vector-copy cadddr caddr vector-copy! vector-fill! cdaaar cdaadr vector-for-each vector-length cdaar cdadar vector-map vector-ref cdaddr cdadr vector-set! vector? cddaar cddadr when with-exception-handler cddar cdddar write-bytevector write-char cddddr cdddr write-string write-u8 zero? Eval Library Case-Lambda Library The (scheme eval) library exports procedures for evalu- ating Scheme data as programs. The (scheme case-lambda) library exports the case-lambda syntax. environment eval

case-lambda File Library Char Library The (scheme file) library provides procedures for access- ing files. The (scheme char) library provides procedures for deal- ing with Unicode character operations. call-with-input-file call-with-output-file delete-file file-exists? char-alphabetic? char-ci<=? open-binary-input-file open-binary-output-file char-ci=? char-ci>? with-input-from-file with-output-to-file char-downcase char-foldcase char-lower-case? char-numeric? char-upcase char-upper-case? Inexact Library char-whitespace? digit-value string-ci<=? string-ci=? are typically only useful with inexact values. string-ci>? string-downcase string-foldcase string-upcase acos asin atan cos exp finite? Complex Library infinite? log nan? sin The (scheme complex) library exports procedures which sqrt tan are typically only useful with non-real numbers.

angle imag-part Lazy Library magnitude make-polar make-rectangular real-part The (scheme lazy) library exports procedures and syntax keywords for lazy evaluation. Appendix A. Standard Libraries 75

delay delay-force * + force make-promise -/ promise? < <= = > >= abs Load Library acos and The (scheme load) library exports procedures for loading angle append Scheme expressions from files. apply asin assoc assq load assv atan begin boolean? Process-Context Library caaaar caaadr caaar caadar The (scheme process-context) library exports proce- caaddr caadr dures for accessing with the program’s calling context. caar cadaar cadadr cadar command-line emergency-exit caddar cadddr exit caddr cadr get-environment-variable call-with-current-continuation get-environment-variables call-with-input-file call-with-output-file call-with-values car Read Library case cdaaar cdaadr cdaar The (scheme read) library provides procedures for read- cdadar cdaddr ing Scheme objects. cdadr cdar read cddaar cddadr cddar cdddar cddddr cdddr Repl Library cddr cdr The (scheme repl) library exports the ceiling char->integer char-alphabetic? char-ci<=? interaction-environment procedure. char-ci=? char-ci>? char-downcase char-lower-case? char-numeric? char-ready? Time Library char-upcase char-upper-case? The (scheme time) library provides access to time-related char-whitespace? char<=? values. char=? char>? current-jiffy current-second char? close-input-port jiffies-per-second close-output-port complex? cond cons Write Library cos current-input-port current-output-port define The (scheme write) library provides procedures for writ- define-syntax delay ing Scheme objects. denominator display do dynamic-wind display write eof-object? eq? write-shared write-simple equal? eqv? eval even? R5RS Library exact->inexact exact? exp expt The (scheme r5rs) library provides the identifiers floor for-each 5 defined by R RS, except that transcript-on and force gcd transcript-off are not present. Note that the exact if imag-part and inexact procedures appear under their R5RS names inexact->exact inexact? inexact->exact and exact->inexact respectively. How- input-port? integer->char ever, if an implementation does not provide a particular integer? interaction-environment library such as the complex library, the corresponding iden- lambda lcm tifiers will not appear in this library either. length let 76 Revised7 Scheme

let* let-syntax Appendix B. Standard Feature Identi- letrec letrec-syntax fiers list list->string list->vector list-ref An implementation may provide any or all of the fea- list-tail list? ture identifiers listed below for use by cond-expand and load log features, but must not provide a feature identifier if it magnitude make-polar does not provide the corresponding feature. make-rectangular make-string make-vector map r7rs max member All R7RS Scheme implementations have this feature. memq memv min modulo exact-closed negative? newline not null-environment All algebraic operations except / produce exact values null? number->string given exact inputs. number? numerator odd? open-input-file exact-complex open-output-file or Exact complex numbers are provided. output-port? pair? peek-char positive? procedure? quasiquote ieee-float quote quotient Inexact numbers are IEEE 754 binary floating point rational? rationalize values. read read-char real-part real? full-unicode remainder reverse round All Unicode characters present in Unicode version 6.0 scheme-report-environment are supported as Scheme characters. set! set-car! set-cdr! sin ratios sqrt string / with exact arguments produces an exact result when string->list string->number the divisor is nonzero. string->symbol string-append string-ci<=? string-ci=? string-ci>? string-copy This implementation is running on a POSIX system. string-fill! string-length string-ref string-set! windows string<=? string=? string>? string? unix, darwin, gnu-linux, bsd, freebsd, solaris, ... substring symbol->string symbol? tan Operating system flags (perhaps more than one). truncate values vector vector->list i386, x86-64, ppc, sparc, jvm, clr, llvm, ... vector-fill! vector-length CPU architecture flags. vector-ref vector-set! vector? with-input-from-file ilp32, lp64, ilp64, ... with-output-to-file write write-char zero? C memory model flags. big-endian, little-endian Byte order flags.

hnamei The name of this implementation.

hname-versioni The name and version of this implementation. Language changes 77

LANGUAGE CHANGES • Libraries have been added as a new program structure to improve encapsulation and sharing of code. Some existing and new identifiers have been factored out Incompatibilities with R5RS into separate libraries. Libraries can be imported into other libraries or main programs, with controlled ex- This section enumerates the incompatibilities between this 5 posure and renaming of identifiers. The contents of a report and the “Revised report” [2]. library can be made conditional on the features of the This list is not authoritative, but is believed to be cor- implementation on which it is to be used. There is an rect and complete. ˚5rs compatibility library.

• Case sensitivity is now the default in symbols and • Exceptions can now be signaled explicitly with raise, character names. This means that code written un- raise-continuable or error, and can be handled der the assumption that symbols could be written with with-exception-handler and the guard syn- FOO or Foo in some contexts and foo in other con- tax. Any object can specify an error condition; the texts must either be changed, be marked with the new implementation-defined conditions signaled by error #!fold-case directive, or be included in a library us- have a predicate to detect them and accessor functions ing the include-ci library declaration. All standard to retrieve the arguments passed to error. Conditions identifiers are entirely in lower case. signaled by read and by file-related procedures also have predicates to detect them. • The syntax-rules construct now recognizes (under- score) as a wildcard, which means it cannot be used • New disjoint types supporting access to multiple fields as a syntax variable. It can still be used as a literal, can be generated with SRFI 9’s define-record-type. however. • Parameter objects can be created with 5 • The R RS procedures exact->inexact and make-parameter, and dynamically rebound with inexact->exact have been renamed to their parameterize. The procedures current-input-port 6 R RS names, inexact and exact, respectively, as and current-output-port are now param- these names are shorter and more correct. The former eter objects, as is the newly introduced 5 names are still available in the R RS compatibility current-error-port. library. • Bytevectors, homogeneous vectors of integers in the • The guarantee that string comparison (with string

• There are now I/O procedures specific to strings and • The log procedure now accepts a second argument bytevectors. specifying the logarithm base. • The write procedure now generates datum labels • The procedures map and for-each are now required when applied to circular objects. The new procedure to terminate on the shortest list when the inputs have write-simple never generates labels; write-shared different lengths. generates labels for all shared and circular structure. • The procedures member and assoc now take an op- • The R6RS procedure eof-object has been added. tional third argument specifying the equality predicate to be used. • Syntax definitions are now allowed wherever variable definitions are. • The numeric procedures finite?, infinite?, nan?, exact-integer?, square, and exact-integer-sqrt • The syntax-rules construct now allows the ellipsis have been added. symbol to be specified explicitly instead of the default ..., allows template escapes with an ellipsis-prefixed • The procedures -, /, and the character and string com- list, and allows tail patterns to follow an ellipsis pat- parison procedures are now required to support an ar- tern. bitrary number of arguments. • The syntax-error syntax has been added as a way to • The procedures make-list, list-copy, list-set!, signal immediate and more informative errors when a string-map, string-for-each, string->vector, macro is expanded. vector-append, vector-copy, vector-map, vector-for-each, vector->string, vector-copy!, • Internal syntax definitions are now allowed wherever and string-copy! have been added to round out the internal definitions are. sequence operations. • The letrec* binding construct has been added, and • Some string and vector procedures support processing internal define is specified in terms of it. of part of a string or vector using optional start and end arguments. • Support for capturing multiple values has been enhanced with define-values, let-values, and • Some list procedures are now defined on circular lists. let*-values. Standard forms which introduce a body • Implementations may provide any subset of the full now permit passing zero or more than one value to the Unicode repertoire that includes ASCII, but imple- continuations of all non-final forms of the body. mentations must support any such subset in a way • The case conditional now supports => syntax anal- consistent with Unicode. Various character and string ogous to cond not only in regular clauses but in the procedures have been extended accordingly. String else clause as well. comparison remains implementation-dependent, and is no longer required to be consistent with character • To support dispatching on the number of arguments comparison, which is based on Unicode scalar values. passed to a procedure, case-lambda has been added The new digit-value procedure has been added to in its own library. obtain the numerical value of a numeric character. • The convenience conditionals when and unless have • There are now two additional comment syntaxes: #; been added. to skip the next datum, and #| ... |# for nestable block comments. • The behavior of both eq? and eqv? on procedures is now unspecified. • Data prefixed with datum labels #= can be refer- enced with ##, allowing for reading and writing of • The behavior of eqv? on inexact numbers now con- data with shared structure. forms to the R6RS definition. • Strings and symbols now allow mnemonic and numeric • The R6RS procedures boolean=? and symbol=? have escape sequences, and the list of named characters has been added. been extended. • Positive infinity, negative infinity, NaN, and nega- • The procedures file-exists? and delete-file are tive inexact zero have been added to the numeric available in the (scheme file) library. tower as inexact values with the written representa- tions +inf.0, -inf.0, +nan.0, and -0.0 respectively. • An interface to the system environment, command Support for them is not required. The representation line, and process exit status is available in the (scheme -nan.0 is synonymous with +nan.0. process-context) library. Language changes 79

• Procedures for accessing time-related values are avail- • The grouping of standardized identifiers into libraries able in the (scheme time) library. is different from the R6RS approach. In particular, procedures which are optional either expressly or by • A less irregular set of integer division operators is pro- implication in R5RS have been removed from the base vided with new and clearer names. library. Only the base library is an absolute require- • The load procedure now accepts a second argument ment. specifying the environment to load into. • Identifier syntax is not provided. This is a useful • The call-with-current-continuation procedure feature in some situations, but the existence of such now has the synonym call/cc. macros means that neither programmers nor other macros can look at an identifier in an evaluated po- • The semantics of read-eval-print loops are now partly sition and know it is a reference — this in a sense prescribed, requiring the redefinition of procedures, makes all macros slightly weaker. Individual imple- but not syntax keywords, to have retroactive effect. mentations are encouraged to continue experimenting with this and other extensions before further standard- Incompatibilities with the main R6RS document ization is done. • Internal syntax definitions are allowed, but all ref- This section enumerates the incompatibilities between erences to syntax must follow the definition; the R7RS and the “Revised6 report” [1]. even/odd example given in R6RS is not allowed. This list is not authoritative, and may be incomplete. • The R6RS exception system was incorporated as-is, • The syntax of the library system was deliberately cho- but the condition types have been left unspecified. 6 sen to be syntactically different from R6RS, using Specific errors that must be signaled in R RS remain 7 define-library instead of library in order to al- errors in R RS, allowing implementations to provide low easy disambiguation between R6RS and R7RS li- their own extensions. There is no discussion of safety. braries. • Full Unicode support is not required. Normalization • The library system does not support phase distinc- is not provided. Character comparisons are defined by tions, which are unnecessary in the absence of low- Unicode, but string comparisons are implementation- level macros (see below), nor does it support version- dependent, and therefore need not be the lexicographic ing, which is an important feature but deserves more mapping of the corresponding character comparisons 5 experimentation before being standardized. (an incompatibility with R RS). Non-Unicode charac- ters are permitted. • Putting an extra level of indirection around the li- brary body allows room for extensibility. The R6RS • The full numeric tower is optional as in R5RS, syntax provides two positional forms which must be but optional support for IEEE infinities, NaN, and present and must have the correct keywords, export -0.0 was adopted from R6RS. Most clarifications on and import, which does not allow for unambiguous ex- numeric results were also adopted, but the R6RS tensions. The Working Group considers extensibility procedures real-valued?, rational-valued?, and to be important, and so chose a syntax which provides integer-valued? were not. The R6RS division a clear separation between the library declarations and operators div, mod, div-and-mod, div0, mod0 and the Scheme code which makes up the body. div0-and-mod0 are not provided. • The include library declaration makes it easier to in- • When a result is unspecified, it is still required to be clude separate files, and the include-ci variant allows a single value, in the interests of R5RS compatibility. legacy case-insensitive code to be incorporated. However, non-final expressions in a body may return any number of values. • The cond-expand library declaration based on SRFI 0 allows for a more flexible alternative to the R6RS • Because of widespread SRFI 1 support and extensive .impl.sls file naming convention. The list of iden- code that uses it, the semantics of map and for-each tifiers that cond-expand treats as true is available at have been changed to use the SRFI 1 early termination run time using the features procedure. behavior. Likewise assoc and member take an optional equal? argument as in SRFI 1, instead of the separate 7 • Since the R RS library system is straightforward, we assp and memp procedures of R6RS. expect that R6RS implementations will be able to sup- port the define-library syntax in addition to their • The R6RS quasiquote clarifications have been library syntax. adopted, but the Working Group has not seen convinc- 80 Revised7 Scheme

ing enough examples of multiple-argument unquote • The Working Group could not agree on a single design and unquote-splicing, so they are not provided. for hash tables and left them for the large language.

• The R6RS method of specifying mantissa widths was • Sorting, bitwise arithmetic, and enumerations were not adopted. not considered to be sufficiently useful to include in the small language. They will probably be included in the large language. Incompatibilities with the R6RS Standard Li- braries document • Pair and string mutation are too well-established to be relegated to separate libraries. This section enumerates the incompatibilities between R7RS and the R6RS [1] Standard Libraries. This list is not authoritative, and is likely to be incom- ADDITIONAL MATERIAL plete. The Scheme community website at http://schemers.org/ • The low-level macro system and syntax-case were not adopted. There are two general families of macro contains additional resources for learning and program- systems in widespread use — the syntax-case fam- ming, job and event postings, and Scheme user group in- ily and the syntactic-closures family — and they formation. have neither been shown to be equivalent in power A bibliography of Scheme-related research at nor capable of implementing each other. Given this situation, low-level macros have been left to the large http://library.readscheme.org/ language. links to technical papers and theses related to the Scheme language, including both classic papers and recent research. • The new I/O system from R6RS was not adopted. Historically, standardization reflects technologies that On-line Scheme discussions are held using IRC on the have undergone a period of adoption, experimenta- #scheme channel at irc.freenode.net and on the Usenet tion, and usage before incorporation into a standard. discussion group comp.lang.scheme. The Working Group was unhappy with the redun- dant provision of both the new system and the R5RS- compatible “simple I/O” system. However, binary I/O was added using binary ports that are at least potentially disjoint from textual ports and use their own parallel set of procedures.

• String ports are compatible with SRFI 6 rather than R6RS; analogous bytevector ports are also provided.

• The Working Group felt that the R6RS records sys- tem was overly complex, and the two layers poorly integrated. The Working Group spent a lot of time debating this, but in the end decided to simply use a generative version of SRFI 9, which has near-universal support among implementations. The Working Group hopes to provide a more powerful records system in the large language.

• R6RS-style bytevectors are included, but provide only the “u8” procedures in the small language. The lexical syntax uses #u8 for compatibility with SRFI 4, rather than the R6RS #vu8 style. With a library system, it’s easier to change names than reader syntax.

• The utility macros when and unless are provided, but since it would be meaningless to try to use their result, it is left unspecified. Example 81

EXAMPLE (lambda (i) (cond ((= i size) ans) The procedure integrate-system integrates the sys- (else tem (vector-set! ans i (proc i)) 0 yk = fk(y1, y2, . . . , yn), k = 1, . . . , n (loop (+ i 1))))))) (loop 0)))) of differential equations with the method of Runge-Kutta. The parameter system-derivative is a function that (define add-vectors (elementwise +)) takes a system state (a vector of values for the state vari- (define (scale-vector s) ables y1, . . . , yn) and produces a system derivative (the val- 0 0 (elementwise (lambda (x) (* x s)))) ues y1, . . . , yn). The parameter initial-state provides an initial system state, and h is an initial guess for the The map-streams procedure is analogous to map: it length of the integration step. applies its first argument (a procedure) to all the elements The value returned by integrate-system is an infi- of its second argument (a stream). nite stream of system states. (define (map-streams f s) (define (integrate-system system-derivative (cons (f (head s)) initial-state (delay (map-streams f (tail s))))) h) Infinite streams are implemented as pairs whose car (let ((next (runge-kutta-4 system-derivative h))) holds the first element of the stream and whose cdr holds (letrec ((states (cons initial-state a promise to deliver the rest of the stream. (delay (map-streams next (define head car) states))))) (define (tail stream) states))) (force (cdr stream))) The procedure runge-kutta-4 takes a function, f, that produces a system derivative from a system state. It The following illustrates the use of integrate-system produces a function that takes a system state and produces in integrating the system a new system state. dvC vC (define (runge-kutta-4 f h) C = −iL − (let ((*h (scale-vector h)) dt R (*2 (scale-vector 2)) (*1/2 (scale-vector (/ 1 2))) diL L = vC (*1/6 (scale-vector (/ 1 6)))) dt (lambda (y) which models a damped oscillator. ;; y is a system state (let* ((k0 (*h (f y))) (define (damped-oscillator R L C) (k1 (*h (f (add-vectors y (*1/2 k0))))) (lambda (state) (k2 (*h (f (add-vectors y (*1/2 k1))))) (let ((Vc (vector-ref state 0)) (k3 (*h (f (add-vectors y k2))))) (Il (vector-ref state 1))) (add-vectors y (vector (- 0 (+ (/ Vc (* R C)) (/ Il C))) (*1/6 (add-vectors k0 (/ Vc L))))) (*2 k1) (*2 k2) (define the-states k3))))))) (integrate-system (damped-oscillator 10000 1000 .001) (define (elementwise f) ’#(1 0) (lambda vectors .01)) (generate-vector (vector-length (car vectors)) (lambda (i) (apply f (map (lambda (v) (vector-ref v i)) vectors))))))

(define (generate-vector size proc) (let ((ans (make-vector size))) (letrec ((loop 82 Revised7 Scheme

REFERENCES [12] William Clinger. Proper Tail Recursion and Space Efficiency. In Proceedings of the 1998 ACM Confer- ence on Programming Language Design and Imple- [1] Michael Sperber, R. Kent Dybvig, Mathew Flatt, mentation, June 1998. and Anton van Straaten, editors. The revised6 report on the algorithmic language Scheme. Cambridge Uni- [13] Mark Davis, Ken Whistler. Unicode Standard An- versity Press, 2010. nex #15, Unicode Normalization Forms. http:// unicode.org/reports/tr15/, 2010. [2] Richard Kelsey, William Clinger, and Jonathan Rees, editors. The revised5 report on the algorithmic lan- [14] Mark Davis. Unicode Standard Annex #29, Unicode guage Scheme. Higher-Order and Symbolic Compu- Text Segmentation. http://unicode.org/reports/ tation, 11(1):7-105, 1998. tr29/, 2010.

[3] Harold Abelson and Gerald Jay Sussman with Julie [15] R. Kent Dybvig, Robert Hieb, and Carl Bruggeman. Sussman. Structure and Interpretation of Computer Syntactic abstraction in Scheme. Lisp and Symbolic Programs, second edition. MIT Press, Cambridge, Computation 5(4):295–326, 1993. 1996. [16] Carol Fessenden, William Clinger, Daniel P. Fried- [4] Alan Bawden and Jonathan Rees. Syntactic closures. man, and Christopher Haynes. Scheme 311 version 4 In Proceedings of the 1988 ACM Symposium reference manual. Indiana University Computer Sci- and Functional Programming, pages 86–95. ence Technical Report 137, February 1983. Super- seded by [17]. [5] Raymond T. Boute. The Euclidean definition of the functions div and mod. In ACM Transactions on Pro- [17] D. Friedman, C. Haynes, E. Kohlbecker, and gramming Languages and Systems 14(2), pages 127– M. Wand. Scheme 84 interim reference manual. Indi- 144, April 1992. ana University Computer Science Technical Report 153, January 1985. [6] S. Bradner. Key words for use in RFCs to In- dicate Requirement Levels. http://www.ietf.org/ [18] Martin Gardner. Mathematical Games: The fan- rfc/rfc2119.txt, 1997. tastic combinations of John Conway’s new solitaire game “Life.” In Scientific American, 223:120–123, [7] Robert G. Burger and R. Kent Dybvig. Printing October 1970. floating-point numbers quickly and accurately. In Proceedings of the ACM SIGPLAN ’96 Conference [19] IEEE Standard 754-2008. IEEE Standard for on Programming Language Design and Implementa- Floating-Point Arithmetic. IEEE, , 2008. tion, pages 108–116. [20] IEEE Standard 1178-1990. IEEE Standard for the Scheme Programming Language. IEEE, New York, [8] William Clinger, editor. The revised revised report 1991. on Scheme, or an uncommon Lisp. MIT Artificial Intelligence Memo 848, August 1985. Also published [21] Eugene E. Kohlbecker Jr. Syntactic Extensions in as Computer Science Department Technical Report the Programming Language Lisp. PhD thesis, Indi- 174, Indiana University, June 1985. ana University, August 1986.

[9] William Clinger. How to read floating point numbers [22] Eugene E. Kohlbecker Jr., Daniel P. Friedman, accurately. In Proceedings of the ACM SIGPLAN , and Bruce Duba. Hygienic macro ’90 Conference on Programming Language Design expansion. In Proceedings of the 1986 ACM Con- and Implementation, pages 92–101. Proceedings pub- ference on Lisp and Functional Programming, pages lished as SIGPLAN Notices 25(6), June 1990. 151–161.

[10] William Clinger and Jonathan Rees, editors. The [23] Peter Landin. A correspondence between Algol 60 revised4 report on the algorithmic language Scheme. and Church’s lambda notation: Part I. Communica- In ACM Lisp Pointers 4(3), pages 1–55, 1991. tions of the ACM 8(2):89–101, February 1965.

[11] William Clinger and Jonathan Rees. Macros that [24] John McCarthy. Recursive Functions of Symbolic Ex- work. In Proceedings of the 1991 ACM Conference pressions and Their Computation by Machine, Part on Principles of Programming Languages, pages 155– I. Communications of the ACM 3(4):184–195, April 162. 1960. References 83

[25] MIT Department of and Com- [39] Andre van Tonder. SRFI-45: Primitives for Ex- puter Science. Scheme manual, seventh edition. pressing Iterative Lazy Algorithms. http://srfi. September 1984. schemers.org/srfi-45/, 2002. [26] Peter Naur et al. Revised report on the algorith- [40] Martin Gasbichler, Eric Knauel, Michael Sperber mic language Algol 60. Communications of the ACM and Richard Kelsey. How to Add Threads to a Se- 6(1):1–17, January 1963. quential Language Without Getting Tangled Up. Proceedings of the Fourth Workshop on Scheme and [27] Paul Penfield, Jr. Principal values and branch cuts Functional Programming, November 2003. in complex APL. In APL ’81 Conference Proceed- ings, pages 248–256. ACM SIGAPL, San Fran- cisco, September 1981. Proceedings published as APL Quote Quad 12(1), ACM, September 1981. [28] Kent M. Pitman. The revised manual (Sat- urday evening edition). MIT Laboratory for Com- puter Science Technical Report 295, May 1983. [29] Jonathan A. Rees and Norman I. Adams IV. T: A dialect of Lisp or, lambda: The ultimate software tool. In Conference Record of the 1982 ACM Sym- posium on Lisp and Functional Programming, pages 114–122. [30] Jonathan A. Rees, Norman I. Adams IV, and James R. Meehan. The T manual, fourth edition. Yale University Computer Science Department, January 1984. [31] Jonathan Rees and William Clinger, editors. The revised3 report on the algorithmic language Scheme. In ACM SIGPLAN Notices 21(12), pages 37–79, De- cember 1986. [32] John Reynolds. Definitional interpreters for higher order programming languages. In ACM Conference Proceedings, pages 717–740. ACM, 1972. [33] Guy Lewis Steele Jr. and Gerald Jay Sussman. The revised report on Scheme, a dialect of Lisp. MIT Ar- tificial Intelligence Memo 452, January 1978. [34] Guy Lewis Steele Jr. Rabbit: a compiler for Scheme. MIT Artificial Intelligence Laboratory Technical Re- port 474, May 1978. [35] Guy Lewis Steele Jr. Common Lisp: The Language, second edition. Digital Press, Burlington MA, 1990. [36] Gerald Jay Sussman and Guy Lewis Steele Jr. Scheme: an interpreter for extended lambda calcu- lus. MIT Artificial Intelligence Memo 349, December 1975. [37] Joseph E. Stoy. Denotational Semantics: The Scott- Strachey Approach to Programming Language The- ory. MIT Press, Cambridge, 1977. [38] Texas Instruments, Inc. TI Scheme Language Ref- erence Manual. Preliminary version 1.0, November 1985. 84 Revised7 Scheme ALPHABETIC INDEX OF DEFINITIONS OF CONCEPTS, KEYWORDS, AND PROCEDURES

The principal entry for each term, procedure, or keyword is bytevector-append 50 listed first, separated from the other entries by a semicolon. bytevector-copy 50 bytevector-copy! 50 ! 7 bytevector-length 49; 33 ’ 12; 41 bytevector-u8-ref 49 * 36 bytevector-u8-set! 50 + 36; 67 bytevector? 49; 10 , 20; 41 bytevectors 49 ,@ 20 - 36 caaaar 42 -> 7 caaadr 42 . 7 caaar 42 ... 23 caadar 42 / 36 caaddr 42 ; 8 caadr 42 < 36; 67 caar 41 <= 36 cadaar 42 = 36 cadadr 42 => 14 cadar 42 > 36 caddar 42 >= 36 cadddr 42 ? 7 caddr 42 #!fold-case 8 cadr 41 #!no-fold-case 8 call 12 22 call by need 18 ‘ 21 call-with-current-continuation 52; 11, 53, 68 call-with-input-file 56 abs 36; 39 call-with-output-file 56 acos 38 call-with-port 55 and 15; 69 call-with-values 53; 11, 68 angle 39 call/cc 52 append 42 car 41; 67 apply 50; 11, 67 car-internal 67 asin 38 case 14; 68 assoc 43 case-lambda 21; 26, 72 assq 43 cdaaar 42 assv 43 cdaadr 42 atan 38 cdaar 42 cdadar 42 #b 34; 63 cdaddr 42 backquote 20 cdadr 42 base library 5 cdar 41 begin 17; 14, 25, 26, 28, 70 cddaar 42 binary-port? 56 cddadr 42 binding 9 cddar 42 binding construct 9 cdddar 42 body 16; 26, 27 cddddr 42 boolean=? 40 cdddr 42 boolean? 40; 10 cddr 41 bound 9 cdr 41 byte 49 ceiling 37 bytevector 49 char->integer 45 Index 85 char-alphabetic? 45 dynamic environment 19 char-ci<=? 45 dynamic extent 19 char-ci=? 45 #e 34; 62 char-ci>? 45 else 14 char-downcase 45 emergency-exit 60 char-foldcase 45 empty list 40; 10, 41, 42 char-lower-case? 45 environment 55; 60 char-numeric? 45 environment variables 60 char-ready? 58 eof-object 58 char-upcase 45 eof-object? 57; 10 char-upper-case? 45 eq? 31 char-whitespace? 45 equal? 32 char<=? 44 equivalence predicate 30 char=? 44 error-object-irritants 54 char>? 44 error-object-message 54 char? 44; 10 error-object? 54 close-input-port 56 escape procedure 52 close-output-port 56 escape sequence 45 close-port 56 eval 55; 12 comma 20 even? 36 command-line 60 exact 39; 33 comment 8; 62 exact complex number 32 complex? 35; 32 exact-integer-sqrt 38 cond 14; 24, 68 exact-integer? 35 cond-expand 15; 28 exact? 35 cons 41 exactness 32 constant 10 except 25 continuation 52 exception handler 53 cos 38 exit 60 current exception handler 53 exp 38 current-error-port 56 export 28 current-input-port 56 expt 38 60 current-jiffy #f 40 current-output-port 56 false 10; 40 60 current-second features 60 fields 27 #d 34 file-error? 54 define 25; 22 file-exists? 59 define-library 28 finite? 35 define-record-type 27 floor 37 define-syntax 26 floor-quotient 36 define-values 26; 70 floor-remainder 36 definition 25 floor/ 36 delay 18 flush-output-port 59 delay-force 18 for-each 51 delete-file 59 force 18 denominator 37 fresh 13 digit-value 45 display 59 gcd 37 do 17; 71 get-environment-variable 60 dotted pair 40 get-environment-variables 60 86 Revised7 Scheme get-output-bytevector 57 list-set! 42 get-output-string 57 list-tail 42 global environment 30; 9 list? 42 guard 20; 26 load 59 location 10 hygienic 22 log 38

#i 34; 62 macro 21 identifier 7; 9, 62 macro keyword 21 if 13; 66 macro transformer 21 imag-part 39 macro use 21 immutable 10 magnitude 39 implementation extension 33 make-bytevector 49 implementation restriction 6; 33 make-list 42 import 25; 28 make-parameter 19 improper list 41 make-polar 39 include 14; 28 make-promise 19; 18 include-ci 14; 28 make-rectangular 39 include-library-declarations 28 make-string 46 inexact 39 make-vector 48 inexact complex numbers 32 map 50 inexact? 35 max 36 infinite? 35 member 43 initial environment 30 memq 43 input-port-open? 56 memv 43 input-port? 56 min 36 integer->char 45 modulo 37 integer? 35; 32 mutable 10 interaction-environment 55 internal definition 26 nan? 35 internal syntax definition 26 negative? 36 irritants 54 newline 59 newly allocated 30 jiffies 60 nil 40 jiffies-per-second 60 not 40 null-environment 55 keyword 21; 22 null? 42 number 32 lambda 13; 26, 66 number->string 39 lazy evaluation 18 number? 35; 10, 32 lcm 37 numerator 37 length 42; 33 numerical types 32 let 16; 18, 24, 26, 69 let* 16; 26, 69 #o 34; 63 let*-values 17; 26, 70 object 5 let-syntax 22; 26 odd? 36 let-values 17; 26, 70 only 25 letrec 16; 26, 69 open-binary-input-file 56 letrec* 16; 26, 70 open-binary-output-file 56 letrec-syntax 22; 26 open-input-bytevector 57 libraries 5 open-input-file 56 list 40; 42 open-input-string 56 list->string 47 open-output-bytevector 57 list->vector 48 open-output-file 56 list-copy 43 open-output-string 56 list-ref 42 or 15; 69 Index 87 output-port-open? 56 setcar 67 output-port? 56 simplest rational 37 sin 38 pair 40 sqrt 38 pair? 41; 10 square 38 parameter objects 19 string 46 parameterize 20; 26 string->list 47 peek-char 57 string->number 39 peek-u8 58 string->symbol 44 polar notation 35 string->utf8 50 port 55 string->vector 48 port? 56; 10 string-append 47 positive? 36 string-ci<=? 47 predicate 30 string-ci=? 47 procedure call 12 string-ci>? 46 procedure? 50; 10 string-copy 47 promise 18 string-copy! 47 promise? 19 string-downcase 47 proper tail recursion 11 string-fill! 47 string-foldcase 47 quasiquote 20; 41 string-for-each 51 quote 12; 41 string-length 46; 33 quotient 37 string-map 51 string-ref 46 raise 54; 20 string-set! 46; 44 raise-continuable 54 string-upcase 47 rational? 35; 32 string<=? 46 rationalize 37 string=? 47 read-bytevector! 58 string>? 46 read-char 57 string? 46; 10 read-error? 54 substring 47 read-line 57 symbol->string 44; 10 read-string 58 symbol=? 43 read-u8 58 symbol? 43; 10 39 real-part syntactic keyword 9; 8, 21 35; 32 real? syntax definition 26 record types 27 syntax-error 24 record-type definitions 27 syntax-rules 26 records 27 rectangular notation 35 #t 40 referentially transparent 22 tail call 11 region 9; 13, 15, 16, 17, 18 tan 38 remainder 37 textual-port? 56 rename 25; 28 token 61 repl 29 true 10; 13, 14, 40 reverse 42 truncate 37 round 37 truncate-quotient 36 truncate-remainder 36 scheme-report-environment 55 truncate/ 36 set! 13; 26, 66 type 10 set-car! 41 set-cdr! 41 u8-ready? 58 88 Revised7 Scheme unbound 9; 12, 26 unless 15; 69 unquote 41 unquote-splicing 41 unspecified 6 utf8->string 50 valid indexes 46; 48, 49 values 53; 12 variable 9; 8, 12 variable definition 25 vector 48 vector->list 48 vector->string 48 vector-append 49 vector-copy 49 vector-copy! 49 vector-fill! 49 vector-for-each 52 vector-length 48; 33 vector-map 51 vector-ref 48 vector-set! 48 vector? 48; 10 when 15; 69 whitespace 8 with-exception-handler 54 with-input-from-file 56 with-output-to-file 56 write 58; 21 write-bytevector 59 write-char 59 write-shared 58 write-simple 59 write-string 59 write-u8 59

#x 34; 63 zero? 36