r7rs-small-texinfo

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit 22c3d49b6fda769830ee182cd5cb6f7bddfad6a8
parent a4b6859b932ef42a30865acec9a538fa0d069abe
Author: Yuval Langer <yuvallangerontheroad@gmail.com>
Date:   Sat, 27 Jan 2024 17:54:44 +0200

Add more chapters, sections, and subsections.

Diffstat:
Mdoc/r7rs-small/r7rs-small.texinfo | 4991++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 4959 insertions(+), 32 deletions(-)

diff --git a/doc/r7rs-small/r7rs-small.texinfo b/doc/r7rs-small/r7rs-small.texinfo @@ -2320,75 +2320,5002 @@ should permit these actions. @node Variable definitions @section Variable definitions + +A variable definition binds one or more identifiers and specifies an initial value for each of +them. The simplest kind of variable definition takes one of the following forms: + +* (define <variable> <expression>) + +* (define (<variable> <formals>) <body>) + + <Formals> are either a sequence of zero or more variables, or a sequence of one or + more variables followed by a space-delimited period and another variable (as in a + lambda expression). This form is equivalent to + + (define <variable> + (lambda (<formals>) <body>)). +* (define (<variable> .​ ​<formal>) <body>) + + <Formal> is a single variable. This form is equivalent to + + (define <variable> + (lambda <formal> <body>)). + @node Top level definitions @subsection Top level definitions + +At the outermost level of a program, a definition + +(define <variable> <expression>)has essentially the same effect as the assignment +expression (set!​ ​<variable> <expression>)if <variable> is bound to a non-syntax value. +However, if <variable> is not bound, or is a syntactic keyword, then the definition will bind +<variable> to a new location before performing the assignment, whereas it would be an +error to perform a set!​ ​on an unboundvariable. + +(define add3 + (lambda (x) (+ x 3))) +(add3 3) ⟹ 6 +(define first car) +(first '(1 2)) ⟹ 1 + @node Internal definitions @subsection Internal definitions + +Definitions can occur at the beginning of a <body> (that is, the body of a lambda, let, let*, +letrec, letrec*, 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 definitionsas opposed to the global +definitions described above. The variables defined by internal definitions are local to the +<body>. That is, <variable> is bound rather than assigned, and the region of the binding is +the entire <body>. For example, + +(let ((x 5)) + (define foo (lambda (y) (bar x y))) + (define bar (lambda (a b) (+ (* a b) a))) + (foo (+ x 3))) ⟹ 45 An expanded <body> containing internal definitions can always +be converted into a completely equivalent letrec* expression. For example, the let +expression in the above example is equivalent to + +(let ((x 5)) + (letrec* ((foo (lambda (y) (bar x y))) + (bar (lambda (a b) (+ (* a b) a)))) + (foo (+ x 3)))) Just as for the equivalent letrec* expression, it is an error if it is not +possible to evaluate each <expression> of every internal definition in a <body> without +assigning or referring to the value of the corresponding <variable> or the <variable> of +any of the definitions that follow it in <body>. + +It is an error to define the same identifier more than once in the same <body>. + +Wherever an internal definition can occur, (begin <definition1> …) is equivalent to the +sequence of definitions that form the body of the begin. + @node Multiple-value definitions @subsection Multiple-value definitions + +Another kind of definition is provided by define-values, which creates multiple definitions +from a single expression returning multiple values. It is allowed wherever define is +allowed. + +syntax: (define-values <formals> <expression>) + +It is an error if a variable appears more than once in the set of <formals>. + +Semantics: <Expression> is evaluated, and the <formals> are bound to the return values in +the same way that the <formals> in a lambda expression are matched to the arguments in +a procedure call. + +(define-values (x y) (exact-integer-sqrt 17)) +(list x y) ⟹ (4 1) + +(let () + (define-values (x y) (values 1 2)) + (+ x y)) ⟹ 3 + @node Syntax definitions @section Syntax definitions + +Syntax definitions have this form: + +(define-syntax <keyword> <transformer spec>) + +<Keyword> is an identifier, and the <transformer spec> is an instance of syntax-rules. Like +variable definitions, syntax definitions can appear at the outermost level or nested within +a body. + +If the define-syntax occurs at the outermost level, then the global syntactic environment +is extended by binding the <keyword> to the specified transformer, but previous +expansions of any global binding for <keyword> remain unchanged. Otherwise, it is an +internal syntax definition, and is local to the <body> in which it is defined. Any use of a +syntax keyword before its corresponding definition is an error. In particular, a use that +precedes an inner definition will not apply an outer definition. + +(let ((x 1) (y 2)) + (define-syntax swap! + (syntax-rules () + ((swap! a b) + (let ((tmp a)) + (set! a b) + (set! b tmp))))) + (swap! x y) + (list x y)) ⟹ (2 1) + +Macros can expand into definitions in any context that permits them. However, it is an +error for a definition to define an identifier whose binding has to be known in order to +determine the meaning of the definition itself, or of any preceding definition that belongs +to the same group of internal definitions. Similarly, it is an error for an internal definition +to define an identifier whose binding has to be known in order to determine the +boundary between the internal definitions and the expressions of the body it belongs to. +For example, the following are errors: + +(define define 3) + +(begin (define begin list)) + +(let-syntax + ((foo (syntax-rules () + ((foo (proc args ...) body ...) + (define proc + (lambda (args ...) + body ...)))))) + (let ((x 3)) + (foo (plus x y) (+ x y)) + (define foo x) + (plus foo x))) + @node Record-type definitions @section Record-type definitions + +Record-type definitions are used to introduce new data types, called record types. Like other +definitions, they can appear either at the outermost level or in a body. The values of a +record type are called records and are aggregations of zero or more fields, each of which +holds a single location. A predicate, a constructor, and field accessors and mutators are +defined for each record type. + +syntax: (define-record-type <name> + <constructor> <pred> <field> …) + +Syntax: <name> and <pred> are identifiers. The <constructor> is of the form + +(<constructor name> <field name> …)and each <field> is either of the form (<field name> +<accessor name>)or of the form (<field name> <accessor name> <modifier name>) It is an +error for the same identifier to occur more than once as a field name. It is also an error +for the same identifier to occur more than once as an accessor or mutator name. + +The define-record-type construct is generative: each use creates a new record type that is +distinct from all existing types, including Scheme’s predefined types and other record +types — even record types of the same name or structure. + +An instance of define-record-type is equivalent to the following definitions: + +* <name> is bound to a representation of the record type itself. This may be a run-time + object or a purely syntactic representation. The representation is not utilized in this + report, but it serves as a means to identify the record type for use by further language + extensions. + +* <constructor name> is bound to a procedure that takes as many arguments as there + are <field name>s in the (<constructor name> …) subexpression and returns a new + record of type <name>. Fields whose names are listed with <constructor name> have + the corresponding argument as their initial value. The initial values of all other fields are + unspecified. It is an error for a field name to appear in <constructor> but not as a <field + name>. + +* <pred> is bound to a predicate that returns #t when given a value returned by the + procedure bound to <constructor name> and #f for everything else. + +* Each <accessor name> is bound to a procedure that takes a record of type <name> and + returns the current value of the corresponding field. It is an error to pass an accessor a + value which is not a record of the appropriate type. + +* Each <modifier name> is bound to a procedure that takes a record of type <name> and + a value which becomes the new value of the corresponding field; an unspecified value + is returned. It is an error to pass a modifier a first argument which is not a record of + the appropriate type. + +For instance, the following record-type definition + +(define-record-type <pare> + (kons x y) + pare? + (x kar set-kar!) + (y kdr)) +defines kons to be a constructor, kar and kdr to be accessors, set-kar! to be a modifier, +and pare? to be a predicate for instances of <pare>. + +(pare? (kons 1 2)) ⟹ #t + (pare? (cons 1 2)) ⟹ #f + (kar (kons 1 2)) ⟹ 1 + (kdr (kons 1 2)) ⟹ 2 + (let ((k (kons 1 2))) + (set-kar! k 3) + (kar k)) ⟹ 3 + @node Libraries @section Libraries + +Libraries provide a way to organize Scheme programs into reusable parts with explicitly +defined interfaces to the rest of the program. This section defines the notation and +semantics for libraries. + @node Library Syntax @subsection Library Syntax + +A library definition takes the following form: + +(define-library <library name> + <library declaration> …) +<library name> is a list whose members are identifiers and exact non-negative integers. It +is used to identify the library uniquely when importing from other programs or libraries. +Libraries whose first identifier is scheme are reserved for use by this report and future +versions of this report. Libraries whose first identifier is srfi are reserved for libraries +implementing Scheme Requests for Implementation. It is inadvisable, but not an error, +for identifiers in library names to contain any of the characters | \ ? * < " : > + [ ] / or +control characters after escapes are expanded. + +A <library declaration> is any of: + +* (export <export spec> …) + +* (import <import set> …) + +* (begin <command or definition> …) + +* (include <filename1> <filename2> …) + +* (include-ci <filename1> <filename2> …) + +* (include-library-declarations <filename1> <filename2> …) + +* (cond-expand <ce-clause1> <ce-clause2> …) + +An export declaration specifies a list of identifiers which can be made visible to other +libraries or programs. An <export spec> takes one of the following forms: + +* <identifier> + +* (rename <identifier1> <identifier2>) + +In an <export spec>, an <identifier> names a single binding defined within or imported +into the library, where the external name for the export is the same as the name of the +binding within the library. A rename spec exports the binding defined within or imported +into the library and named by <identifier1> in each (<identifier1> <identifier2>) pairing, +using <identifier2> as the external name. + +An import declaration provides a way to import the identifiers exported by another +library. It has the same syntax and semantics as an import declaration used in a program +or at the REPL (see section 5.2). + +The begin, include, and include-ci declarations are used to specify the body of the library. +They have the same syntax and semantics as the corresponding expression types. This +form of begin is analogous to, but not the same as, the two types of begin defined in +section 4.2.3. + +The include-library-declarations declaration is similar to include except that the contents +of the file are spliced directly into the current library definition. This can be used, for +example, to share the same export declaration among multiple libraries as a simple form +of library interface. + +The cond-expand declaration has the same syntax and semantics as the cond-expand +expression type, except that it expands to spliced-in library declarations rather than +expressions enclosed in begin. + +One possible implementation of libraries is as follows: After all cond-expand library +declarations are expanded, a new environment is constructed for the library consisting of +all imported bindings. The expressions from all begin, include and include-ci library +declarations are expanded in that environment in the order in which they occur in the +library. Alternatively, cond-expand and import declarations may be processed in left to +right order interspersed with the processing of other declarations, with the environment +growing as imported bindings are added to it by each import declaration. + +When a library is loaded, its expressions are executed in textual order. If a library’s +definitions are referenced in the expanded form of a program or library body, then that +library must be loaded before the expanded program or library body is evaluated. This +rule applies transitively. If a library is imported by more than one program or library, it +may possibly be loaded additional times. + +Similarly, during the expansion of a library (foo), if any syntax keywords imported from +another library (bar) are needed to expand the library, then the library (bar) must be +expanded and its syntax definitions evaluated before the expansion of (foo). + +Regardless of the number of times that a library is loaded, each program or library that +imports bindings from a library must do so from a single loading of that library, +regardless of the number of import declarations in which it appears. That is, (import (only +(foo) a)) followed by (import (only (foo) b)) has the same effect as (import (only (foo) a b)). + @node Library example @subsection Library example + +The following example shows how a program can be divided into libraries plus a relatively +small main program [16]. If the main program is entered into a REPL, it is not necessary to +import the base library. + +(define-library (example grid) + (export make rows cols ref each + (rename put! set!)) + (import (scheme base)) + (begin + ;; Create an NxM grid. + (define (make n m) + (let ((grid (make-vector n))) + (do ((i 0 (+ i 1))) + ((= i n) grid) + (let ((v (make-vector m #false))) + (vector-set! grid i v))))) + (define (rows grid) + (vector-length grid)) + (define (cols grid) + (vector-length (vector-ref grid 0))) + ;; Return #false if out of range. + (define (ref grid n m) + (and (< -1 n (rows grid)) + (< -1 m (cols grid)) + (vector-ref (vector-ref grid n) m))) + (define (put! grid n m v) + (vector-set! (vector-ref grid n) m v)) + (define (each grid proc) + (do ((j 0 (+ j 1))) + ((= j (rows grid))) + (do ((k 0 (+ k 1))) + ((= k (cols grid))) + (proc j k (ref grid j k))))))) + +(define-library (example life) + (export life) + (import (except (scheme base) set!) + (scheme write) + (example grid)) + (begin + (define (life-count grid i j) + (define (count i j) + (if (ref grid i j) 1 0)) + (+ (count (- i 1) (- j 1)) + (count (- i 1) j) + (count (- i 1) (+ j 1)) + (count i (- j 1)) + (count i (+ j 1)) + (count (+ i 1) (- j 1)) + (count (+ i 1) j) + (count (+ i 1) (+ j 1)))) + (define (life-alive? grid i j) + (case (life-count grid i j) + ((3) #true) + ((2) (ref grid i j)) + (else #false))) + (define (life-print grid) + (display "\x1B;[1H\x1B;[J") ; clear vt100 + (each grid + (lambda (i j v) + (display (if v "*" " ")) + (when (= j (- (cols grid) 1)) + (newline))))) + (define (life grid iterations) + (do ((i 0 (+ i 1)) + (grid0 grid grid1) + (grid1 (make (rows grid) (cols grid)) + grid0)) + ((= i iterations)) + (each grid0 + (lambda (j k v) + (let ((a (life-alive? grid0 j k))) + (set! grid1 j k a)))) + (life-print grid1))))) + +;; Main program. +(import (scheme base) + (only (example life) life) + (rename (prefix (example grid) grid-) + (grid-make make-grid))) + +;; Initialize a grid with a glider. +(define grid (make-grid 24 24)) +(grid-set! grid 1 1 #true) +(grid-set! grid 2 2 #true) +(grid-set! grid 3 0 #true) +(grid-set! grid 3 1 #true) +(grid-set! grid 3 2 #true) + +;; Run for 80 iterations. +(life grid 80) + @node The REPL @section The REPL +Implementations may provide an interactive session called a REPL (Read-Eval-Print Loop), +where import declarations, expressions and definitions can be entered and evaluated one +at a time. For convenience and ease of use, the global Scheme environment in a REPL +must not be empty, but must start out with at least the bindings provided by the base +library. This library includes the core syntax of Scheme and generally useful procedures +that manipulate data. For example, the variable abs is bound to a procedure of one +argument that computes the absolute value of a number, and the variable + is bound to a +procedure that computes sums. The full list of (scheme base) bindings can be found in +Appendix A. + +Implementations may provide an initial REPL environment which behaves as if all possible +variables are bound to locations, most of which contain unspecified values. Top level REPL +definitions in such an implementation are truly equivalent to assignments, unless the +identifier is defined as a syntax keyword. + +An implementation may provide a mode of operation in which the REPL reads its input +from a file. Such a file is not, in general, the same as a program, because it can contain +import declarations in places other than the beginning. + @node Standard procedures @chapter Standard procedures + +This chapter describes Scheme’s built-in procedures. The procedures force, promise?, and +make-promise are intimately associated with the expression types delay and delay-force, +and are described with them in section 4.2.5. In the same way, the procedure +make-parameter is intimately associated with the expression type parameterize, and is +described with it in section 4.2.6. + +A program can use a global variable definition to bind any variable. It may subsequently +alter any such binding by an assignment (see section 4.1.6). These operations do not +modify the behavior of any procedure defined in this report or imported from a library +(see section 5.6). Altering any global binding that has not been introduced by a definition +has an unspecified effect on the behavior of the procedures defined in this chapter. + +When a procedure is said to return a newly allocated object, it means that the locations in +the object are fresh. + @node Equivalence predicates @section Equivalence predicates + +A predicate is a procedure that always returns a boolean value (#t or #f). An equivalence +predicate is the computational analogue of a mathematical equivalence relation; it is +symmetric, reflexive, and transitive. Of the equivalence predicates described in this +section, eq?​ ​is the finest or most discriminating, equal?​ ​is the coarsest, and eqv?​ ​is +slightly less discriminating than eq?. + +procedure: (eqv? + +obj1 + +obj2) + + +The eqv? procedure defines a useful equivalence relation on objects. Briefly, it returns #t +if + +obj1 and + +obj2 are normally regarded as the same object. This relation is left slightly open to +interpretation, but the following partial specification of eqv? holds for all implementations +of Scheme. + +The eqv? procedure returns #t if: + +* obj1 and + + obj2 are both #t or both #f. + +* obj1 and + + obj2 are both symbols and are the same symbol according to the symbol=? procedure + (section 6.5). + +* obj1 and + + obj2 are both exact numbers and are numerically equal (in the sense of =). + +* obj1 and + + obj2 are both inexact numbers such that they are numerically equal (in the sense of =) + and they yield the same results (in the sense of eqv?) when passed as arguments to any + other procedure that can be defined as a finite composition of Scheme’s standard + arithmetic procedures, provided it does not result in a NaN value. + +* obj1 and + + obj2 are both characters and are the same character according to the char=? procedure + (section 6.6). + +* obj1 and + + obj2 are both the empty list. + +* obj1 and + + obj2 are pairs, vectors, bytevectors, records, or strings that denote the same location in + the store (section 3.4). + +* obj1 and + + obj2 are procedures whose location tags are equal (section 4.1.4). + +The eqv? procedure returns #f if: + +* obj1 and + + obj2 are of different types (section 3.2). + +* one of + + obj1 and + + obj2 is #t but the other is #f. + +* obj1 and + + obj2 are symbols but are not the same symbol according to the symbol=? procedure + (section 6.5). + +* one of + + obj1 and + + obj2 is an exact number but the other is an inexact number. + +* obj1 and + + obj2 are both exact numbers and are numerically unequal (in the sense of =). + +* obj1 and + + obj2 are both inexact numbers such that either they are numerically unequal (in the + sense of =), or they do not yield the same results (in the sense of eqv?) when passed as + arguments to any other procedure that can be defined as a finite composition of + Scheme’s standard arithmetic procedures, provided it does not result in a NaN value. As + an exception, the behavior of eqv? is unspecified when both + + obj1 and + + obj2 are NaN. + +* obj1 and + + obj2 are characters for which the char=? procedure returns #f. + +* one of + + obj1 and + + obj2 is the empty list but the other is not. + +* obj1 and + + obj2 are pairs, vectors, bytevectors, records, or strings that denote distinct locations. + +* obj1 and + + obj2 are procedures that would behave differently (return different values or have + different side effects) for some arguments. + +(eqv? 'a 'a) ⟹ #t +(eqv? 'a 'b) ⟹ #f +(eqv? 2 2) ⟹ #t +(eqv? 2 2.0) ⟹ #f +(eqv? '() '()) ⟹ #t +(eqv? 100000000 100000000) ⟹ #t +(eqv? 0.0 +nan.0) ⟹ #f +(eqv? (cons 1 2) (cons 1 2)) ⟹ #f +(eqv? (lambda () 1) + (lambda () 2)) ⟹ #f +(let ((p (lambda (x) x))) + (eqv? p p)) ⟹ #t +(eqv? #f 'nil) ⟹ #f The following examples illustrate cases in which the above rules +do not fully specify the behavior of eqv?. All that can be said about such cases is that the +value returned by eqv? must be a boolean. + +(eqv? "" "") ⟹ unspecified +(eqv? '#() '#()) ⟹ unspecified +(eqv? (lambda (x) x) + (lambda (x) x)) ⟹ unspecified +(eqv? (lambda (x) x) + (lambda (y) y)) ⟹ unspecified +(eqv? 1.0e0 1.0f0) ⟹ unspecified +(eqv? +nan.0 +nan.0) ⟹ unspecified Note that (eqv? 0.0 -0.0) will return #f if negative zero +is distinguished, and #t if negative zero is not distinguished. + +The next set of examples shows the use of eqv?​ ​with procedures that have local state. The +gen-counter procedure must return a distinct procedure every time, since each +procedure has its own internal counter. The gen-loser procedure, however, returns +operationally equivalent procedures each time, since the local state does not affect the +value or side effects of the procedures. However, eqv? may or may not detect this +equivalence. + +(define gen-counter + (lambda () + (let ((n 0)) + (lambda () (set! n (+ n 1)) n)))) +(let ((g (gen-counter))) + (eqv? g g)) ⟹ #t +(eqv? (gen-counter) (gen-counter)) + ⟹ #f +(define gen-loser + (lambda () + (let ((n 0)) + (lambda () (set! n (+ n 1)) 27)))) +(let ((g (gen-loser))) + (eqv? g g)) ⟹ #t +(eqv? (gen-loser) (gen-loser)) + ⟹ unspecified + +(letrec ((f (lambda () (if (eqv? f g) 'both 'f))) + (g (lambda () (if (eqv? f g) 'both 'g)))) + (eqv? f g)) + ⟹ unspecified + +(letrec ((f (lambda () (if (eqv? f g) 'f 'both))) + (g (lambda () (if (eqv? f g) 'g 'both)))) + (eqv? f g)) + ⟹ #f Since it is an error to modify constant objects (those returned by literal +expressions), implementations may share structure between constants where +appropriate. Thus the value of eqv? on constants is sometimes +implementation-dependent. + +(eqv? '(a) '(a)) ⟹ unspecified +(eqv? "a" "a") ⟹ unspecified +(eqv? '(b) (cdr '(a b))) ⟹ unspecified +(let ((x '(a))) + (eqv? x x)) ⟹ #t The above definition of eqv? allows implementations latitude in +their treatment of procedures and literals: implementations may either detect or fail to +detect that two procedures or two literals are equivalent to each other, and can decide +whether or not to merge representations of equivalent objects by using the same pointer +or bit pattern to represent both. + + Note: If inexact numbers are represented as IEEE binary floating-point numbers, then + an implementation of eqv? that simply compares equal-sized inexact numbers for + bitwise equality is correct by the above definition. + +procedure: (eq? + +obj1 + +obj2) + + +The eq?​ ​procedure is similar to eqv?​ ​except that in some cases it is capable of discerning +distinctions finer than those detectable by eqv?. It must always return #f when eqv?​ ​also +would, but may return #f in some cases where eqv?​ ​would return #t. + +On symbols, booleans, the empty list, pairs, and records, and also on non-empty strings, +vectors, and bytevectors, eq?​ ​and eqv?​ ​are guaranteed to have the same behavior. On +procedures, eq?​ ​must return true if the arguments’ location tags are equal. On numbers +and characters, eq?’s behavior is implementation-dependent, but it will always return +either true or false. On empty strings, empty vectors, and empty bytevectors, eq? may also +behave differently from eqv?. + +(eq? 'a 'a) ⟹ #t +(eq? '(a) '(a)) ⟹ unspecified +(eq? (list 'a) (list 'a)) ⟹ #f +(eq? "a" "a") ⟹ unspecified +(eq? "" "") ⟹ unspecified +(eq? '() '()) ⟹ #t +(eq? 2 2) ⟹ unspecified +(eq? #\A #\A) ⟹ unspecified +(eq? car car) ⟹ #t +(let ((n (+ 2 3))) + (eq? n n)) ⟹ unspecified +(let ((x '(a))) + (eq? x x)) ⟹ #t +(let ((x '#())) + (eq? x x)) ⟹ #t +(let ((p (lambda (x) x))) + (eq? p p)) ⟹ #t + + Rationale: It will usually be possible to implement eq?​ ​much more efficiently than + eqv?, for example, as a simple pointer comparison instead of as some more + complicated operation. One reason is that it is not always possible to compute eqv?​ + ​of two numbers in constant time, whereas eq?​ ​implemented as pointer comparison + will always finish in constant time. + +procedure: (equal? + +obj1 + +obj2) + + +The equal? procedure, when applied to pairs, vectors, strings and bytevectors, recursively +compares them, returning #t when the unfoldings of its arguments into (possibly infinite) +trees are equal (in the sense of equal?) as ordered trees, and #f otherwise. It returns the +same as eqv? when applied to booleans, symbols, numbers, characters, ports, +procedures, and the empty list. If two objects are eqv?, they must be equal? as well. In all +other cases, equal? may return either #t or #f. Even if its arguments are circular data +structures, equal?​ ​must always terminate. + +(equal? 'a 'a) ⟹ #t +(equal? '(a) '(a)) ⟹ #t +(equal? '(a (b) c) + '(a (b) c)) ⟹ #t +(equal? "abc" "abc") ⟹ #t +(equal? 2 2) ⟹ #t +(equal? (make-vector 5 'a) + (make-vector 5 'a)) ⟹ #t +(equal? '#1=(a b . #1#) + '#2=(a b a b . #2#)) ⟹ #t +(equal? (lambda (x) x) + (lambda (y) y)) ⟹ unspecified + + Note: A rule of thumb is that objects are generally equal? if they print the same. + @node Numbers @section Numbers + +It is important to distinguish between mathematical numbers, the Scheme numbers that +attempt to model them, the machine representations used to implement the Scheme +numbers, and notations used to write numbers. This report uses the types number, +complex, real, rational, and integer to refer to both mathematical numbers and Scheme +numbers. + @node Numerical types @subsection Numerical types + +Mathematically, numbers are arranged into a tower of subtypes in which each level is a +subset of the level above it: + +​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​​ ​number + complex number + real number + rational number + integer + +For example, 3 is an integer. Therefore 3 is also a rational, a real, and a complex number. +The same is true of the Scheme numbers that model 3. For Scheme numbers, these types +are defined by the predicates number?, complex?, real?, rational?, and integer?. + +There is no simple relationship between a number’s type and its representation inside a +computer. Although most implementations of Scheme will offer at least two different +representations of 3, these different representations denote the same integer. + +Scheme’s numerical operations treat numbers as abstract data, as independent of their +representation as possible. Although an implementation of Scheme may use multiple +internal representations of numbers, this ought not to be apparent to a casual +programmer writing simple programs. + @node Exactness @subsection Exactness + +It is useful to distinguish between numbers that are represented exactly and those that +might not be. For example, indexes into data structures must be known exactly, as must +some polynomial coefficients in a symbolic algebra system. On the other hand, the results +of measurements are inherently inexact, and irrational numbers may be approximated by +rational and therefore inexact approximations. In order to catch uses of inexact numbers +where exact numbers are required, Scheme explicitly distinguishes exact from inexact +numbers. This distinction is orthogonal to the dimension of type. + +A Scheme number is exact if it was written as an exact constant or was derived from exact +numbers using only exact operations. A number is inexact if it was written as an inexact +constant, if it was derived using inexact ingredients, or if it was derived using inexact +operations. Thus inexactness is a contagious property of a number. In particular, an exact +complex number has an exact real part and an exact imaginary part; all other complex +numbers are inexact complex numbers. + +If two implementations produce exact results for a computation that did not involve +inexact intermediate results, the two ultimate results will be mathematically equal. This 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 +implementation to make the result as close as practical to the mathematically ideal result. + +Rational operations such as + should always produce exact results when given exact +arguments. If the operation is unable to produce an exact result, then it may either report +the violation of an implementation restriction or it may silently coerce its result to an +inexact value. However, (/ 3 4) must not return the mathematically incorrect value 0. See +section 6.2.3. + +Except for exact, the operations described in this section must generally return inexact +results when given any inexact arguments. An operation may, however, return an exact +result if it can prove that the value of the result is unaffected by the inexactness of its +arguments. For example, multiplication of any number by an exact zero may produce an +exact zero result, even if the other argument is inexact. + +Specifically, the expression (* 0 +inf.0) may return 0, or +nan.0, or report that inexact +numbers are not supported, or report that non-rational real numbers are not supported, +or fail silently or noisily in other implementation-specific ways. + @node Implementation restrictions @subsection Implementation restrictions + +Implementations of Scheme are not required to implement the whole tower of subtypes +given in section 6.2.1, but they must implement a coherent subset consistent with both +the purposes of the implementation and the spirit of the Scheme language. For example, +implementations in which all numbers are real, or in which non-real numbers are always +inexact, or in which exact numbers are always integer, are still quite useful. + +Implementations may also support only a limited range of numbers of any type, subject to +the requirements of this section. The supported range for exact numbers of any type may +be different from the supported range for inexact numbers of that type. For example, an +implementation that uses IEEE binary double-precision floating-point numbers to +represent all its inexact real numbers may also support a practically unbounded range of +exact integers and rationals while limiting the range of inexact reals (and therefore the +range of inexact integers and rationals) to the dynamic range of the IEEE binary double +format. Furthermore, the gaps between the representable inexact integers and rationals +are likely to be very large in such an implementation as the limits of this range are +approached. + +An implementation of Scheme must support exact integers throughout the range of +numbers permitted as indexes of lists, vectors, bytevectors, and strings or that result from +computing the length of one of these. The length, vector-length, bytevector-length, and +string-length procedures must return an exact integer, and it is an error to use anything +but an exact integer as an index. Furthermore, any integer constant within the index +range, if expressed by an exact integer syntax, must be read as an exact integer, +regardless of any implementation restrictions that apply outside this range. Finally, the +procedures listed below will always return exact integer results provided all their +arguments are exact integers and the mathematically expected results are representable +as exact integers within the implementation: + +- * ++ abs +ceiling denominator +exact-integer-sqrt expt +floor floor/ +floor-quotient floor-remainder +gcd lcm +max min +modulo numerator +quotient rationalize +remainder round +square truncate +truncate/ truncate-quotient +truncate-remainder +It is recommended, but not required, that implementations support exact integers and +exact rationals of practically unlimited size and precision, and to implement the above +procedures and the / procedure in such a way that they always return exact results when +given exact arguments. If one of these procedures is unable to deliver an exact result +when given exact arguments, then it may either report a violation of an implementation +restriction or it may silently coerce its result to an inexact number; such a coercion can +cause an error later. Nevertheless, implementations that do not provide exact rational +numbers should return inexact rational numbers rather than reporting an +implementation restriction. + +An implementation may use floating-point and other approximate representation +strategies for inexact numbers. This report recommends, but does not require, that +implementations that use floating-point representations follow the IEEE 754 standard, +and that implementations using other representations should match or exceed the +precision achievable using these floating-point standards [17]. In particular, the +description of transcendental functions in IEEE 754-2008 should be followed by such +implementations, particularly with respect to infinities and NaNs. + +Although Scheme allows a variety of written notations for numbers, any particular +implementation may support only some of them. For example, an implementation in +which all numbers are real need not support the rectangular and polar notations for +complex numbers. If an implementation encounters an exact numerical constant that it +cannot represent as an exact number, then it may either report a violation of an +implementation restriction or it may silently represent the constant by an inexact +number. + @node Implementation extensions @subsection Implementation extensions + +Implementations may provide more than one representation of floating-point numbers +with differing precisions. In an implementation which does so, an inexact result must be +represented with at least as much precision as is used to express any of the inexact +arguments to that operation. Although it is desirable for potentially inexact operations +such as sqrt to produce exact answers when applied to exact arguments, if an exact +number is operated upon so as to produce an inexact result, then the most precise +representation available must be used. For example, the value of (sqrt 4) should be 2, but +in an implementation that provides both single and double precision floating point +numbers it may be the latter but must not be the former. + +It is the programmer’s responsibility to avoid using inexact number objects with +magnitude or significand too large to be represented in the implementation. + +In addition, implementations may distinguish special numbers called positive infinity, +negative infinity, NaN, and negative zero. + +Positive infinity is regarded as an inexact real (but not rational) number that represents an +indeterminate value greater than the numbers represented by all rational numbers. +Negative infinity is regarded as an inexact real (but not rational) number that represents +an indeterminate value less than the numbers represented by all rational numbers. + +Adding or multiplying an infinite value by any finite real value results in an appropriately +signed infinity; however, the sum of positive and negative infinities is a NaN. Positive +infinity is the reciprocal of zero, and negative infinity is the reciprocal of negative zero. +The behavior of the transcendental functions is sensitive to infinity in accordance with +IEEE 754. + +A NaN is regarded as an inexact real (but not rational) number so indeterminate that it +might represent any real value, including positive or negative infinity, and might even be +greater than positive infinity or less than negative infinity. An implementation that does +not support non-real numbers may use NaN to represent non-real values like (sqrt -1.0) +and (asin 2.0). + +A NaN always compares false to any number, including a NaN. An arithmetic operation +where one operand is NaN returns NaN, unless the implementation can prove that the +result would be the same if the NaN were replaced by any rational number. Dividing zero +by zero results in NaN unless both zeros are exact. + +Negative zero is an inexact real value written -0.0 and is distinct (in the sense of eqv?) from +0.0. A Scheme implementation is not required to distinguish negative zero. If it does, +however, the behavior of the transcendental functions is sensitive to the distinction in +accordance with IEEE 754. Specifically, in a Scheme implementing both complex numbers +and negative zero, the branch cut of the complex logarithm function is such that +(imag-part (log -1.0-0.0i)) is −π rather than π. + +Furthermore, the negation of negative zero is ordinary zero and vice versa. This implies +that the sum of two or more negative zeros is negative, and the result of subtracting +(positive) zero from a negative zero is likewise negative. However, numerical comparisons +treat negative zero as equal to zero. + +Note that both the real and the imaginary parts of a complex number can be infinities, +NaNs, or negative zero. + @node Syntax of numerical constants @subsection Syntax of numerical constants + +The syntax of the written representations for numbers is described formally in section +7.1.1. Note that case is not significant in numerical constants. + +A number can be written in binary, octal, decimal, or hexadecimal by the use of a radix +prefix. The radix prefixes are #b(binary), #o(octal), #d(decimal), and #x(hexadecimal). With +no radix prefix, a number is assumed to be expressed in decimal. + +A numerical constant can be specified to be either exact or inexact by a prefix. The +prefixes are #efor exact, and #ifor inexact. An exactness prefix can appear before or after +any radix prefix that is used. If the written representation of a number has no exactness +prefix, the constant is inexact if it contains a decimal point or an exponent. Otherwise, it is +exact. + +In systems with inexact numbers of varying precisions it can be useful to specify the +precision of a constant. For this purpose, implementations may accept numerical +constants written with an exponent marker that indicates the desired precision of the +inexact representation. If so, the letter s, f, d, or l, meaning + +short, + +single, + +double, or + +long precision, respectively, can be used in place of e. The default precision has at least as +much precision as + +double, but implementations may allow this default to be set by the user. + +3.14159265358979F0 + Round to single --- 3.141593 +0.6L0 + Extend to long --- .600000000000000 The numbers positive infinity, negative infinity, +and NaN are written +inf.0, -inf.0 and +nan.0 respectively. NaN may also be written -nan.0. +The use of signs in the written representation does not necessarily reflect the underlying +sign of the NaN value, if any. Implementations are not required to support these +numbers, but if they do, they must do so in general conformance with IEEE 754. However, +implementations are not required to support signaling NaNs, nor to provide a way to +distinguish between different NaNs. + +There are two notations provided for non-real complex numbers: the rectangular notation + +a+ + +bi, where + +a is the real part and + +b is the imaginary part; and the polar notation + +r@θ, where + +r is the magnitude and θ is the phase (angle) in radians. These are related by the equation +a + bi = r cos θ + (r sin θ) i. All of + +a, + +b, + +r, and θ are real numbers. + @node Numerical operations @subsection Numerical operations -@node Numerical input and output -@subsection Numerical input and output -@node Booleans -@section Booleans -@node Pairs and lists -@section Pairs and lists -@node Symbols -@section Symbols -@node Characters -@section Characters -@node Strings -@section Strings -@node Vectors -@section Vectors -@node Bytevectors -@section Bytevectors -@node Control features -@section Control features -@node Exceptions -@section Exceptions -@node Environments and evaluation -@section Environments and evaluation -@node Input and output -@section Input and output -@node Ports -@subsection Ports -@node Input -@subsection Input -@node Output -@subsection Output -@node System interface -@section System interface + +The reader is referred to section 1.3.3 for a summary of the naming conventions used to +specify restrictions on the types of arguments to numerical routines. The examples used +in this section assume that any numerical constant written using an exact notation is +indeed represented as an exact number. Some examples also assume that certain +numerical constants written using an inexact notation 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 represent inexact numbers. + +procedure: (number? obj) +procedure: (complex? obj) +procedure: (real? obj) +procedure: (rational? obj) +procedure: (integer? obj) + +These numerical type predicates can be applied to any kind of argument, including +non-numbers. They return #t if the object is of the named type, and otherwise they return +#f. In general, if a type predicate is true of a number then all higher type predicates are +also true of that number. Consequently, if a type predicate is false of a number, then all +lower type predicates are also false of that number. + +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 (= + +x (round + +x)). + +The numbers +inf.0, -inf.0, and +nan.0 are real but not rational. + +(complex? 3+4i) ⟹ #t +(complex? 3) ⟹ #t +(real? 3) ⟹ #t +(real? -2.5+0i) ⟹ #t +(real? -2.5+0.0i) ⟹ #f +(real? #e1e10) ⟹ #t +(real? +inf.0) ⟹ #t +(real? +nan.0) ⟹ #t +(rational? -inf.0) ⟹ #f +(rational? 3.5) ⟹ #t +(rational? 6/10) ⟹ #t +(rational? 6/3) ⟹ #t +(integer? 3+0i) ⟹ #t +(integer? 3.0) ⟹ #t +(integer? 8/4) ⟹ #t + + Note: The behavior of these type predicates on inexact numbers is unreliable, since + any inaccuracy might affect the result. + + Note: In many implementations the complex? procedure will be the same as + number?, but unusual implementations may represent some irrational numbers + exactly or may extend the number system to support some kind of non-complex + numbers. + +procedure: (exact? + +z) + + +procedure: (inexact? + +z) + + +These numerical predicates provide tests for the exactness of a quantity. For any Scheme +number, precisely one of these predicates is true. + +(exact? 3.0) ⟹ #f +(exact? #e3.0) ⟹ #t +(inexact? 3.) ⟹ #t + +procedure: (exact-integer? + +z) + + +Returns #t if + +z is both exact and an integer; otherwise returns #f. + +(exact-integer? 32) ⟹ #t +(exact-integer? 32.0) ⟹ #f +(exact-integer? 32/5) ⟹ #f + +inexact library procedure: (finite? + +z) + + +The finite? procedure returns #t on all real numbers except +inf.0, -inf.0, and +nan.0, and +on complex numbers if their real and imaginary parts are both finite. Otherwise it returns +#f. + +(finite? 3) ⟹ #t +(finite? +inf.0) ⟹ #f +(finite? 3.0+inf.0i) ⟹ #f + +inexact library procedure: (infinite? + +z) + + +The infinite? procedure returns #t on the real numbers +inf.0 and -inf.0, and on complex +numbers if their real or imaginary parts or both are infinite. Otherwise it returns #f. + +(infinite? 3) ⟹ #f +(infinite? +inf.0) ⟹ #t +(infinite? +nan.0) ⟹ #f +(infinite? 3.0+inf.0i) ⟹ #t + +inexact library procedure: (nan? + +z) + + +The nan? procedure returns #t on +nan.0, and on complex numbers if their real or +imaginary parts or both are +nan.0. Otherwise it returns #f. + +(nan? +nan.0) ⟹ #t +(nan? 32) ⟹ #f +(nan? +nan.0+5.0i) ⟹ #t +(nan? 1+2i) ⟹ #f + +procedure: (= + +z1 + +z2 + +z3 …) + + +procedure: (< + +x1 + +x2 + +x3 …) + + +procedure: (> + +x1 + +x2 + +x3 …) + + +procedure: (<= + +x1 + +x2 + +x3 …) + + +procedure: (>= + +x1 + +x2 + +x3 …) + + +These procedures return #t if their arguments are (respectively): equal, monotonically +increasing, monotonically decreasing, 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 distinguish between inexact zero and inexact negative zero. + +These predicates are required to be transitive. + + Note: The implementation approach of converting all arguments to inexact numbers + if any argument is inexact is not transitive. For example, let big be (expt 2 1000), and + assume that big is exact and that inexact numbers are represented by 64-bit IEEE + binary floating point numbers. Then (= (- big 1) (inexact big)) and (= (inexact big) (+ big + 1)) would both be true with this approach, because of the limitations of IEEE + representations of large integers, whereas (= (- big 1) (+ big 1)) is false. Converting + inexact values to exact numbers that are the same (in the sense of =) to them will + avoid this problem, though special care must be taken with infinities. + + Note: While it is not an error to compare inexact numbers using these predicates, the + results are unreliable because a small inaccuracy can affect the result; this is + especially true of = and zero?. When in doubt, consult a numerical analyst. + +procedure: (zero? + +z) + + +procedure: (positive? + +x) + + +procedure: (negative? + +x) + + +procedure: (odd? + +n) + + +procedure: (even? + +n) + + +These numerical predicates test a number for a particular property, returning #t or #f. +See note above. + +procedure: (max + +x1 + +x2 …) + + +procedure: (min + +x1 + +x2 …) + + +These procedures return the maximum or minimum of their arguments. + +(max 3 4) ⟹ 4 ; exact +(max 3.9 4) ⟹ 4.0 ; inexact + + Note: If any argument is inexact, then the result will also be inexact (unless the + procedure can prove that the inaccuracy is not large enough to affect the result, + which is possible only in unusual implementations). If min or max is used to compare + numbers of mixed exactness, and the numerical value of the result cannot be + represented as an inexact number without loss of accuracy, then the procedure may + report a violation of an implementation restriction. + +procedure: (+ + +z1 …) + + +procedure: (* + +z1 …) + + +These procedures return the sum or product of their arguments. + +(+ 3 4) ⟹ 7 +(+ 3) ⟹ 3 +(+) ⟹ 0 +(* 4) ⟹ 4 +(*) ⟹ 1 + +procedure: (- + +z) + + +procedure: (- + +z1 + +z2 …) + + +procedure: (/ + +z) + + +procedure: (/ + +z1 + +z2 …) + + +With two or more arguments, these procedures return the difference or quotient of their +arguments, associating to the left. With one argument, however, they return the additive +or multiplicative inverse of their argument. + +It is an error if any argument of / other than the first is an exact zero. If the first +argument is an exact zero, an implementation may return an exact zero unless one of the +other arguments is a NaN. + +(- 3 4) ⟹ -1 +(- 3 4 5) ⟹ -6 +(- 3) ⟹ -3 +(/ 3 4 5) ⟹ 3/20 +(/ 3) ⟹ 1/3 + +procedure: (abs x) + +The abs procedure returns the absolute value of its argument. + +(abs -7) ⟹ 7 + +procedure: (floor/ + +n1 + +n2) + + +procedure: (floor-quotient + +n1 + +n2) + + +procedure: (floor-remainder + +n1 + +n2) + + +procedure: (truncate/ + +n1 + +n2) + + +procedure: (truncate-quotient + +n1 + +n2) + + +procedure: (truncate-remainder + +n1 + +n2) + + +These procedures implement number-theoretic (integer) division. It is an error if + +n2 is zero. The procedures ending in / return two integers; the other procedures return an +integer. All the procedures compute a quotient + +nq and remainder + +nr such that + +n1 = + +n2 + +nq + + +nr. For each of the division operators, there are three procedures defined as follows: + +(<operator>/ + +n1 + +n2) ⟹ + +nq + +nr +(<operator>-quotient + +n1 + +n2) ⟹ + +nq +(<operator>-remainder + +n1 + +n2) ⟹ + +nr + +The remainder + +nr is determined by the choice of integer + +nq: + +nr = + +n1 − + +n2 + +nq. Each set of operators uses a different choice of + +nq: + + floor nq = ⌊ + + n1 / + + n2⌋ + truncate nq = texttruncate( + + n1 / + + n2) + +For any of the operators, and for integers + +n1 and + +n2 with + +n2 not equal to 0, + +(= + +n1 (+ (* + +n2 (<operator>-quotient + +n1 + +n2)) + (<operator>-remainder + +n1 + +n2))) + ⟹ #t + +provided all numbers involved in that computation are exact. + +Examples: + +(floor/ 5 2) ⟹ 2 1 +(floor/ -5 2) ⟹ -3 1 +(floor/ 5 -2) ⟹ -3 -1 +(floor/ -5 -2) ⟹ 2 -1 +(truncate/ 5 2) ⟹ 2 1 +(truncate/ -5 2) ⟹ -2 -1 +(truncate/ 5 -2) ⟹ -2 1 +(truncate/ -5 -2) ⟹ 2 -1 +(truncate/ -5.0 -2) ⟹ 2.0 -1.0 + +procedure: (quotient + +n1 + +n2) + + +procedure: (remainder + +n1 + +n2) + + +procedure: (modulo + +n1 + +n2) + + +The quotient and remainder procedures are equivalent to truncate-quotient and +truncate-remainder, respectively, and modulo is equivalent to floor-remainder. + + Note: These procedures are provided for backward compatibility with earlier + versions of this report. + +procedure: (gcd + +n1 …) + + +procedure: (lcm + +n1 …) + + +These procedures return the greatest common divisor or least common multiple of their +arguments. The result is always non-negative. + +(gcd 32 -36) ⟹ 4 +(gcd) ⟹ 0 +(lcm 32 -36) ⟹ 288 +(lcm 32.0 -36) ⟹ 288.0 ; inexact +(lcm) ⟹ 1 + +procedure: (numerator + +q) + + +procedure: (denominator + +q) + + +These procedures return the numerator or denominator of their argument; the result is +computed as if the argument was represented as a fraction in lowest terms. The +denominator is always positive. The denominator of 0 is defined to be 1. + +(numerator (/ 6 4)) ⟹ 3 +(denominator (/ 6 4)) ⟹ 2 +(denominator + (inexact (/ 6 4))) ⟹ 2.0 + +procedure: (floor x) +procedure: (ceiling x) +procedure: (truncate x) +procedure: (round x) + +These procedures return integers. The floor procedure returns the largest integer not +larger than + +x. The ceiling procedure returns the smallest integer not smaller than + +x, truncate returns the integer closest to + +x whose absolute value is not larger than the absolute value of + +x, and round returns the closest integer to + +x, rounding to even when + +x is halfway between two integers. + + Rationale: The round procedure rounds to even for consistency with the default + rounding mode specified by the IEEE 754 IEEE floating-point standard. + + Note: If the argument to one of these procedures is inexact, then the result will also + be inexact. If an exact value is needed, the result can be passed to the exact + procedure. If the argument is infinite or a NaN, then it is returned. + +(floor -4.3) ⟹ -5.0 +(ceiling -4.3) ⟹ -4.0 +(truncate -4.3) ⟹ -4.0 +(round -4.3) ⟹ -4.0 + +(floor 3.5) ⟹ 3.0 +(ceiling 3.5) ⟹ 4.0 +(truncate 3.5) ⟹ 3.0 +(round 3.5) ⟹ 4.0 ; inexact + +(round 7/2) ⟹ 4 ; exact +(round 7) ⟹ 7 + +procedure: (rationalize x y) + +The rationalize procedure returns the simplest rational number differing from + +x by no more than + +y. A rational number r1 is simpler than another rational number r2 if r1 = p1/q1 and r2 = +p2/q2 (in lowest terms) and |p1| ≤|p2| 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 simpler than every other rational number in +that interval (the simpler 2/5 lies between 2/7 and 3/5). Note that 0 = 0/1 is the simplest +rational of all. + +(rationalize + (exact .3) 1/10) ⟹ 1/3 ; exact +(rationalize .3 1/10) ⟹ #i1/3 ; inexact + +inexact library procedure: (exp + +z) + + +inexact library procedure: (log + +z) + + +inexact library procedure: (log + +z1 + +z2) + + +inexact library procedure: (sin + +z) + + +inexact library procedure: (cos + +z) + + +inexact library procedure: (tan + +z) + + +inexact library procedure: (asin + +z) + + +inexact library procedure: (acos + +z) + + +inexact library procedure: (atan + +z) + + +inexact library procedure: (atan + +y + +x) + + +These procedures compute the usual transcendental functions. 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 given. The asin, acos, and atan procedures compute arcsine (sin +−1), arc-cosine (cos −1), and arctangent (tan −1), respectively. The two-argument variant +of atan computes (angle (make-rectangular + +x + +y)) (see below), even in implementations that don’t support complex numbers. + +In general, the mathematical functions log, arcsine, arc-cosine, and arctangent are +multiply defined. The value of log z is defined to be the one whose imaginary part lies in +the range from −π (inclusive if -0.0 is distinguished, exclusive otherwise) to π (inclusive). +The value of log 0 is mathematically undefined. With log defined this way, the values of +sin −1z, cos −1z, and tan −1z are according to the following formulæ: + + sin −1z = −i log (i z + (1 − + z2)1/2) + + cos −1z = π/ 2 − sin −1z + + tan −1z = (log (1 + i z) − log (1 − i z)) / + (2 i) + +However, (log 0.0) returns -inf.0 (and (log -0.0) returns -inf.0+πi) if the implementation +supports infinities (and -0.0). + +The range of (atan + +y + +x) is as in the following table. The asterisk (*) indicates that the entry applies to +implementations that distinguish minus zero. + + y condition x condition range of result r + y = 0.0 x > 0.0 0.0 + ∗ y = + 0.0 x > 0.0 + 0.0 + ∗ y = −0.0 x > 0.0 −0.0 + y > 0.0 x > 0.0 0.0 < r < π/2 + y > 0.0 x = 0.0 π/2 + y > 0.0 x < 0.0 π/2 < r < π + y = 0.0 x < 0 π + ∗ y = + 0.0 x < 0.0 π + ∗ y = −0.0 x < 0.0 −π + y < 0.0 x < 0.0 −π< r< −π/2 + y < 0.0 x = 0.0 −π/2 + y < 0.0 x > 0.0 −π/2 < r< 0.0 + y = 0.0 x = 0.0 undefined + ∗ y = + 0.0 x = + 0.0 + 0.0 + ∗ y = −0.0 x = + 0.0 −0.0 + ∗ y = + 0.0 x = −0.0 π + ∗ y = −0.0 x = −0.0 −π + ∗ y = + 0.0 x = 0 π/2 + ∗ y = −0.0 x = 0 −π/2 +The above specification follows [34], which in turn cites [26]; refer to these sources for +more detailed discussion of branch cuts, boundary conditions, and implementation of +these functions. When it is possible, these procedures produce a real result from a real +argument. + +procedure: (square + +z) + + +Returns the square of + +z. This is equivalent to (* + +z + +z). + +(square 42) ⟹ 1764 +(square 2.0) ⟹ 4.0 + +inexact library procedure: (sqrt + +z) + + +Returns the principal square root of + +z. The result will have either a positive real part, or a zero real part and a non-negative +imaginary part. + +(sqrt 9) ⟹ 3 +(sqrt -1) ⟹ +i + +procedure: (exact-integer-sqrt k) + +Returns two non-negative exact integers s and r where + +k = s2 + r and + +k < (s + 1)2. + +(exact-integer-sqrt 4) ⟹ 2 0 +(exact-integer-sqrt 5) ⟹ 2 1 + +procedure: (expt + +z1 + +z2) + + +Returns + +z1 raised to the power + +z2. For nonzero + +z1, this is + + z1 z2 = ez2 log z1 + +The value of 0z is 1 if (zero? z), 0 if (real-part z) is positive, and an error otherwise. +Similarly for 0.0z, with inexact results. + +complex library procedure: (make-rectangular + +x1 + +x2) + + +complex library procedure: (make-polar + +x3 + +x4) + + +complex library procedure: (real-part + +z) + + +complex library procedure: (imag-part + +z) + + +complex library procedure: (magnitude + +z) + + +complex library procedure: (angle + +z) + + +Let + +x1, + +x2, + +x3, and + +x4 be real numbers and + +z be a complex number such that + + z = x1 + x2 i = x3 · + ei + x4 + +Then all of + +(make-rectangular + +x1 + +x2) ⟹ + +z +(make-polar + +x3 + +x4) ⟹ + +z +(real-part + +z) ⟹ + +x1 +(imag-part + +z) ⟹ + +x2 +(magnitude + +z) ⟹ | + +x3| +(angle + +z) ⟹ xangle + +are true, where −π≤xangle ≤π with xangle = + +x4 + 2πn for some integer n. + +The make-polar procedure may return an inexact complex number even if its arguments +are exact. The real-part and imag-part procedures may return exact real numbers when +applied to an inexact complex number if the corresponding argument passed to +make-rectangular was exact. + + Rationale: The magnitude procedure is the same as abs for a real argument, but abs + is in the base library, whereas magnitude is in the optional complex library. + +procedure: (inexact + +z) + + +procedure: (exact + +z) + + +The procedure inexact returns an inexact representation of + +z. The value returned is the inexact number that is numerically closest to the argument. +For inexact arguments, the result is the same as the argument. For exact complex +numbers, the result is a complex number whose real and imaginary parts are the result +of applying inexact to the real and imaginary parts of the argument, respectively. If an +exact argument has no reasonably close inexact equivalent (in the sense of =), then a +violation of an implementation restriction may be reported. + +The procedure exact returns an exact representation of + +z. The value returned is the exact number that is numerically closest to the argument. +For exact arguments, the result is the same as the argument. For inexact non-integral +real arguments, the implementation may return a rational approximation, or may report +an implementation violation. For inexact complex arguments, the result is a complex +number whose real and imaginary parts are the result of applying exact to the real and +imaginary parts of the argument, respectively. If an inexact argument has no reasonably +close exact equivalent, (in the sense of =), then a violation of an implementation +restriction may be reported. + +These procedures implement the natural one-to-one correspondence between exact and +inexact integers throughout an implementation-dependent range. See section 6.2.3. + + Note: These procedures were known in R5RS​ ​as exact->inexact and inexact->exact, + respectively, but they have always accepted arguments of any exactness. The new + names are clearer and shorter, as well as being compatible with R6RS. + +@node Numerical input and output +@subsection Numerical input and output + +procedure: (number->string z) +procedure: (number->string z radix) + +It is an error if + +radix is not one of 2, 8, 10, or 16. + +The procedure number->string takes a number and a radix and returns as a string an +external representation of the given number in the given radix such that + +(let ((number + +number) + (radix + +radix)) + (eqv? number + (string->number (number->string number + radix) + radix))) + +is true. It is an error if no possible result makes this expression true. If omitted, + +radix defaults to 10. + +If + +z is inexact, the radix is 10, and the above expression can be satisfied by a result that +contains a decimal point, then the result contains a decimal point and is expressed using +the minimum number of digits (exclusive of exponent and trailing zeroes) needed to +make the above expression true [4, 5]; otherwise the format of the result is unspecified. + +The result returned by number->string never contains an explicit radix prefix. + + Note: The error case can occur only when + + z is not a complex number or is a complex number with a non-rational real or + imaginary part. + + Rationale: If + + z is an inexact number and the radix is 10, then the above expression is normally + satisfied by a result containing a decimal point. The unspecified case allows for + infinities, NaNs, and unusual representations. + +procedure: (string->number string) +procedure: (string->number string radix) + +Returns a number of the maximally precise representation expressed by the given + +string. + +It is an error if + +radix is not 2, 8, 10, or 16. + +If supplied, + +radix is a default radix that will be overridden if an explicit radix prefix is present in + +string (e.g. "#o177"). If + +radix is not supplied, then the default radix is 10. If + +string is not a syntactically valid notation for a number, or would result in a number that +the implementation cannot represent, then string->number returns #f. An error is never +signaled due to the content of + +string. + +(string->number "100") ⟹ 100 +(string->number "100" 16) ⟹ 256 +(string->number "1e2") ⟹ 100.0 + + Note: The domain of string->number may be restricted by implementations in the + following ways. If all numbers supported by an implementation are real, then + string->number is permitted to return #f whenever + + string uses the polar or rectangular notations for complex numbers. If all numbers + are integers, then string->number may return #f whenever the fractional notation is + used. If all numbers are exact, then string->number may return #f whenever an + exponent marker or explicit exactness prefix is used. If all inexact numbers are + integers, then string->number may return #f whenever a decimal point is used. + + The rules used by a particular implementation for string->number must also be + applied to read and to the routine that reads programs, in order to maintain + consistency between internal numeric processing, I/O, and the processing of + programs. As a consequence, the R5RS​ ​permission to return #f when + + string has an explicit radix prefix has been withdrawn. + +@node Booleans +@section Booleans + +The standard boolean objects for true and false are written as #t and #f.Alternatively, +they can be written #true and #false, respectively. What really matters, though, are the +objects that the Scheme conditional expressions (if, cond, and, or, when, unless, do) +treat as trueor false. The phrase “a true value”(or sometimes just “true”) means any +object treated as true by the conditional expressions, and the phrase “a false value”(or +“false”) means any object treated as false by the conditional expressions. + +Of all the Scheme values, only #f counts as false in conditional expressions. All other +Scheme values, including #t, count as true. + + Note: Unlike some other dialects of Lisp, Scheme distinguishes #f and the empty list + from each other and from the symbol nil. + +Boolean constants evaluate to themselves, so they do not need to be quoted in +programs. + +#t ⟹ #t +#f ⟹ #f +'#f ⟹ #f + +procedure: (not obj) + +The not procedure returns #t if + +obj is false, and returns #f otherwise. + +(not #t) ⟹ #f +(not 3) ⟹ #f +(not (list 3)) ⟹ #f +(not #f) ⟹ #t +(not '()) ⟹ #f +(not (list)) ⟹ #f +(not 'nil) ⟹ #f + +procedure: (boolean? obj) + +The boolean? predicate returns #t if + +obj is either #t or #f and returns #f otherwise. + +(boolean? #f) ⟹ #t +(boolean? 0) ⟹ #f +(boolean? '()) ⟹ #f + +procedure: (boolean=? + +boolean1 + +boolean2 + +boolean3 …) + + +Returns #t if all the arguments are #t or all are #f. + +@node Pairs and lists +@section Pairs and lists + +A pair (sometimes called a dotted pair) is a record structure with two fields called the car +and cdr fields (for historical reasons). Pairs are created by the procedure cons. The car +and cdr fields are accessed by the procedures car and cdr. The car and cdr fields are +assigned by the procedures set-car!​ ​and set-cdr!. + +Pairs are used primarily to represent lists. A list can be defined recursively as either the +empty listor a pair whose cdr is a list. More precisely, the set of lists is defined as the +smallest set + +X such that + +* The empty list is in + + X. + +* If + + list is in + + X, then any pair whose cdr field contains + + list is also in + + X. + +The objects in the car fields of successive pairs of a list are the elements of the list. For +example, a two-element list is a pair whose car is the first element and whose cdr is a +pair whose car is the second element and whose cdr is the empty list. The length of a list +is the number of elements, which is the same as the number of pairs. + +The empty listis a special object of its own type. It is not a pair, it has no elements, and its +length is zero. + + Note: The above definitions imply that all lists have finite length and are terminated + by the empty list. + +The most general notation (external representation) for 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 field. For example (4 .​ ​5) is a pair whose car is 4 and whose cdr is +5. Note that (4 .​ ​5) is the external representation of a pair, not an expression that +evaluates to a pair. + +A more streamlined notation can be used for lists: the elements of the list are simply +enclosed in parentheses and separated by spaces. The empty listis written (). For +example, + +(a b c d e) and + +(a . (b . (c . (d . (e . ()))))) are equivalent notations for a list of symbols. + +A chain of pairs not ending in the empty list is called an improper list. Note that an +improper list is not a list. The list and dotted notations can be combined to represent +improper lists: + +(a b c . d) is equivalent to + +(a . (b . (c . d))) Whether a given pair is a list depends upon what is stored in the cdr field. +When the set-cdr! procedure is used, an object can be a list one moment and not the +next: + +(define x (list 'a 'b 'c)) +(define y x) +y ⟹ (a b c) +(list? y) ⟹ #t +(set-cdr! x 4) ⟹ unspecified +x ⟹ (a . 4) +(eqv? x y) ⟹ #t +y ⟹ (a . 4) +(list? y) ⟹ #f +(set-cdr! x x) ⟹ unspecified +(list? x) ⟹ #f Within literal expressions and representations of objects read by the +read procedure, the forms '<datum>, `<datum>, ,<datum>, and ,@<datum> denote +two-element lists whose first elements are the symbols quote, quasiquote, unquote, and +unquote-splicing, respectively. The second element in each case is <datum>. This +convention is supported so that arbitrary Scheme programs can be represented as lists. +That is, according to Scheme’s grammar, every <expression> is also a <datum> (see +section 7.1.2). Among other things, this permits the use of the read procedure to parse +Scheme programs. See section 3.3. + +procedure: (pair? obj) + +The pair? predicate returns #t if + +obj is a pair, and otherwise returns #f. + +(pair? '(a . b)) ⟹ #t +(pair? '(a b c)) ⟹ #t +(pair? '()) ⟹ #f +(pair? '#(a b)) ⟹ #f + +procedure: (cons + +obj1 + +obj2) + + +Returns a newly allocated pair whose car is + +obj1 and whose cdr is + +obj2. The pair is guaranteed to be different (in the sense of eqv?) from every existing +object. + +(cons 'a '()) ⟹ (a) +(cons '(a) '(b c d)) ⟹ ((a) b c d) +(cons "a" '(b c)) ⟹ ("a" b c) +(cons 'a 3) ⟹ (a . 3) +(cons '(a b) 'c) ⟹ ((a b) . c) + +procedure: (car pair) + +Returns the contents of the car field of + +pair. Note that it is an error to take the car of the empty list. + +(car '(a b c)) ⟹ a +(car '((a) b c d)) ⟹ (a) +(car '(1 . 2)) ⟹ 1 +(car '()) ⟹ error + +procedure: (cdr pair) + +Returns the contents of the cdr field of + +pair. Note that it is an error to take the cdr of the empty list. + +(cdr '((a) b c d)) ⟹ (b c d) +(cdr '(1 . 2)) ⟹ 2 +(cdr '()) ⟹ error + +procedure: (set-car! pair obj) + +Stores + +obj in the car field of + +pair. + +(define (f) (list 'not-a-constant-list)) +(define (g) '(constant-list)) +(set-car! (f) 3) ⟹ unspecified +(set-car! (g) 3) ⟹ error + +procedure: (set-cdr! pair obj) + +Stores + +obj in the cdr field of + +pair. + +procedure: (caar pair) +procedure: (cadr pair) +procedure: (cdar pair) +procedure: (cddr pair) + +These procedures are compositions of car and cdr as follows: + +(define (caar x) (car (car x))) +(define (cadr x) (car (cdr x))) +(define (cdar x) (cdr (car x))) +(define (cddr x) (cdr (cdr x))) + +cxr library procedure: (caaar pair) +cxr library procedure: (caadr pair) +1 ⋮: 0 ⋮ +cxr library procedure: (cdddar pair) +cxr library procedure: (cddddr pair) + +These twenty-four procedures are further compositions of car and cdr on the same +principles. For example, caddr could be defined by + +(define caddr (lambda (x) (car (cdr (cdr x))))). Arbitrary compositions up to four deep are +provided. + +procedure: (null? obj) + +Returns #t if + +obj is the empty list, otherwise returns #f. + +procedure: (list? obj) + +Returns #t if + +obj is a list. Otherwise, it returns #f. By definition, all lists have finite length and are +terminated by the empty list. + +(list? '(a b c)) ⟹ #t + (list? '()) ⟹ #t + (list? '(a . b)) ⟹ #f + (let ((x (list 'a))) + (set-cdr! x x) + (list? x)) ⟹ #f + +procedure: (make-list k) +procedure: (make-list k fill) + +Returns a newly allocated list of + +k elements. If a second argument is given, then each element is initialized to + +fill. Otherwise the initial contents of each element is unspecified. + +(make-list 2 3) ⟹ (3 3) + +procedure: (list + +obj …) + + +Returns a newly allocated list of its arguments. + +(list 'a (+ 3 4) 'c) ⟹ (a 7 c) +(list) ⟹ () + +procedure: (length list) + +Returns the length of + +list. + +(length '(a b c)) ⟹ 3 +(length '(a (b) (c d e))) ⟹ 3 +(length '()) ⟹ 0 + +procedure: (append list …) + +The last argument, if there is one, can be of any type. + +Returns a list consisting of the elements of the first + +list followed by the elements of the other + +lists. If there are no arguments, the empty list is returned. If there is exactly one +argument, it is returned. Otherwise the resulting list is always newly allocated, except +that it shares structure with the last argument. An improper list results if the last +argument is not a proper list. + +(append '(x) '(y)) ⟹ (x y) +(append '(a) '(b c d)) ⟹ (a b c d) +(append '(a (b)) '((c))) ⟹ (a (b) (c)) + +(append '(a b) '(c . d)) ⟹ (a b c . d) +(append '() 'a) ⟹ a + +procedure: (reverse list) + +Returns a newly allocated list consisting of the elements of + +list in reverse order. + +(reverse '(a b c)) ⟹ (c b a) +(reverse '(a (b c) d (e (f)))) +⟹ ((e (f)) d (b c) a) + +procedure: (list-tail list + +k) + + +It is an error if + +list has fewer than + +k elements. + +Returns the sublist of + +list obtained by omitting the first + +k elements. The list-tail procedure could be defined by + +(define list-tail + (lambda (x k) + (if (zero? k) + x + (list-tail (cdr x) (- k 1))))) + +procedure: (list-ref list + +k) + + +The + +list argument can be circular, but it is an error if + +list has + +k or fewer elements. + +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-ref '(a b c d) + (exact (round 1.8))) +⟹ c + +procedure: (list-set! list k obj) + +It is an error if + +k is not a valid index of + +list. + +The list-set! procedure stores + +obj in element + +k of + +list. + +(let ((ls (list 'one 'two 'five!))) + (list-set! ls 2 'three) + ls) +⟹ (one two three) + +(list-set! '(0 1 2) 1 "oops") +⟹ error ; constant list + +procedure: (memq obj list) +procedure: (memv obj list) +procedure: (member obj list) +procedure: (member obj list compare) + +These procedures return the first sublist of + +list whose car is + +obj, where the sublists of + +list are the non-empty lists 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 list) is returned. The memq procedure uses eq?​ ​to compare + +obj with the elements of + +list, while memv uses eqv? and member uses + +compare, if given, and equal? otherwise. + +(memq 'a '(a b c)) ⟹ (a b c) +(memq 'b '(a b c)) ⟹ (b c) +(memq 'a '(b c d)) ⟹ #f +(memq (list 'a) '(b (a) c)) ⟹ #f +(member (list 'a) + '(b (a) c)) ⟹ ((a) c) +(member "B" + '("a" "b" "c") + string-ci=?) ⟹ ("b" "c") +(memq 101 '(100 101 102)) ⟹ unspecified +(memv 101 '(100 101 102)) ⟹ (101 102) + +procedure: (assq obj alist) +procedure: (assv obj alist) +procedure: (assoc obj alist) +procedure: (assoc obj alist compare) + +It is an error if + +alist (for “association list”) is not a list of pairs. + +These procedures find the first pair in + +alist whose car field 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 assq procedure uses eq?​ ​to +compare + +obj with the car fields of the pairs in + +alist, while assv uses eqv?​ ​and assoc uses + +compare if given and equal? otherwise. + +(define e '((a 1) (b 2) (c 3))) +(assq 'a e) ⟹ (a 1) +(assq 'b e) ⟹ (b 2) +(assq 'd e) ⟹ #f +(assq (list 'a) '(((a)) ((b)) ((c)))) + ⟹ #f +(assoc (list 'a) '(((a)) ((b)) ((c)))) + ⟹ ((a)) +(assoc 2.0 '((1 1) (2 4) (3 9)) =) + ⟹ (2 4) +(assq 5 '((2 3) (5 7) (11 13))) + ⟹ unspecified +(assv 5 '((2 3) (5 7) (11 13))) + ⟹ (5 7) + + Rationale: Although they are often used as predicates, memq, memv, member, assq, + assv, and assoc do not have question marks in their names because they return + potentially useful values rather than just #t or #f. + +procedure: (list-copy obj) + +Returns a newly allocated copy of the given + +obj if it is a list. Only the pairs themselves are copied; the cars of the result are the same +(in the sense of eqv?) as the cars of + +list. If + +obj is an improper list, so is the result, and the final cdrs are the same in the sense of +eqv?. An + +obj which is not a list is returned unchanged. It is an error if + +obj is a circular list. + +(define a '(1 8 2 8)) ; a may be immutable +(define b (list-copy a)) +(set-car! b 3) ; b is mutable +b ⟹ (3 8 2 8) +a ⟹ (1 8 2 8) + +@node Symbols +@section Symbols + +Symbols are objects whose usefulness rests on the fact that two symbols are identical (in +the sense of eqv?) if and only if their names are spelled the same way. For instance, they +can be used the way enumerated values are used in other languages. + +The rules for writing a symbol are exactly the same as the rules for writing an identifier; +see sections 2.1 and 7.1.1. + +It is guaranteed that any symbol that has been returned as part of a literal expression, +or read using the read procedure, and subsequently written out using the write +procedure, will read back in as the identical symbol (in the sense of eqv?). + + Note: Some implementations have values known as “uninterned symbols,” which + defeat write/read invariance, and also violate the rule that two symbols are the + same if and only if their names are spelled the same. This report does not specify + the behavior of implementation-dependent extensions. + +procedure: (symbol? obj) + +Returns #t if + +obj is a symbol, otherwise returns #f. + +(symbol? 'foo) ⟹ #t +(symbol? (car '(a b))) ⟹ #t +(symbol? "bar") ⟹ #f +(symbol? 'nil) ⟹ #t +(symbol? '()) ⟹ #f +(symbol? #f) ⟹ #f + +procedure: (symbol=? + +symbol1 + +symbol2 + +symbol3 …) + + +Returns #t if all the arguments all have the same names in the sense of string=?. + + Note: The definition above assumes that none of the arguments are uninterned + symbols. + +procedure: (symbol->string symbol) + +Returns the name of + +symbol as a string, but without adding escapes. It is an error to apply mutation +procedures like string-set! to strings returned by this procedure. + +(symbol->string 'flying-fish) + ⟹ "flying-fish" +(symbol->string 'Martin) ⟹ "Martin" +(symbol->string + (string->symbol "Malvina")) + ⟹ "Malvina" + +procedure: (string->symbol string) + +Returns the symbol whose name is + +string. This procedure can create symbols with names containing special characters that +would require escaping when written, but does not interpret escapes in its input. + +(string->symbol "mISSISSIppi") +⟹mISSISSIppi +(eqv? 'bitBlt (string->symbol "bitBlt")) +⟹ #t +(eqv? 'LollyPop + (string->symbol + (symbol->string 'LollyPop))) +⟹ #t +(string=? "K. Harper, M.D." + (symbol->string + (string->symbol "K. Harper, M.D."))) +⟹ #t + +@node Characters +@section Characters + +Characters are objects that represent printed characters such as letters and digits. All +Scheme implementations must support at least the ASCII character repertoire: that is, +Unicode characters U+0000 through U+007F. Implementations may support any other +Unicode characters they see fit, and may also support non-Unicode characters as well. +Except as otherwise specified, the result of applying any of the following procedures to a +non-Unicode character is implementation-dependent. + +Characters are written using the notation #\<character> or #\<character name> or +#\x<hex scalar value>. + +The following character names must be supported by all implementations with the given +values. Implementations may add other names provided they cannot be interpreted as +hex scalar values preceded by x. + + #\alarm ; U+0007 + #\backspace ; U+0008 + #\delete ; U+007F + #\escape ; U+001B + #\newline ; the + linefeed + character, + U+000A + #\null ; the null + character, + U+0000 + #\return ; the + return + character, + U+000D + #\space ; the + preferred + way to + write a + space + #\tab ; the tab + character, + U+0009 + +Here are some additional examples: + + #\a ; lower case + letter + #\A ; upper case + letter + #\( ; left + parenthesis + #\ ; the space + character + #\x03BB ; λ (if + character is + supported) + #\iota ; ι (if + character + and name + are + supported) + +Case is significant in #\<character>, and in #\⟨character name⟩, but not in #\x<hex scalar +value>. If <character> in #\<character> is alphabetic, then any character immediately +following <character> cannot be one that can appear in an identifier. This rule resolves +the ambiguous case where, for example, the sequence of characters “#\space” could be +taken to be either a representation of the space character or a representation of the +character “#\s” followed by a representation of the symbol “pace.” + +Characters written in the #\ notation are self-evaluating. That is, they do not have to be +quoted in programs. Some of the procedures that operate on characters ignore the +difference between upper case and lower case. The procedures that ignore case have +“-ci” (for “case insensitive”) embedded in their names. + +procedure: (char? obj) + +Returns #t if + +obj is a character, otherwise returns #f. + +procedure: (char=? + +char1 + +char2 + +char3 …) + + +procedure: (char<? + +char1 + +char2 + +char3 …) + + +procedure: (char>? + +char1 + +char2 + +char3 …) + + +procedure: (char<=? + +char1 + +char2 + +char3 …) + + +procedure: (char>=? + +char1 + +char2 + +char3 …) + + +These procedures return #t if the results of passing their arguments to char->integer +are respectively equal, monotonically increasing, monotonically decreasing, +monotonically non-decreasing, or monotonically non-increasing. + +These predicates are required to be transitive. + +char library procedure: (char-ci=? + +char1 + +char2 + +char3 …) + + +char library procedure: (char-ci<? + +char1 + +char2 + +char3 …) + + +char library procedure: (char-ci>? + +char1 + +char2 + +char3 …) + + +char library procedure: (char-ci<=? + +char1 + +char2 + +char3 …) + + +char library procedure: (char-ci>=? + +char1 + +char2 + +char3 …) + + +These procedures are similar to char=?​ ​et cetera, but they treat upper case and lower +case letters as the same. For example, (char-ci=?​ ​#\A #\a) returns #t. + +Specifically, these procedures behave as if char-foldcase were applied to their +arguments before they were compared. + +char library procedure: (char-alphabetic? char) +char library procedure: (char-numeric? char) +char library procedure: (char-whitespace? char) +char library procedure: (char-upper-case? letter) +char library procedure: (char-lower-case? letter) + +These procedures return #t if their arguments are alphabetic, numeric, whitespace, +upper case, or lower case characters, respectively, otherwise they return #f. Specifically, +they must return #t when applied to characters with the Unicode properties Alphabetic, +Numeric_Type=Decimal, White_Space, Uppercase, and Lowercase respectively, and #f +when applied to any other Unicode characters. Note that many Unicode characters are +alphabetic but neither upper nor lower case. + +char library procedure: (digit-value char) + +This procedure returns the numeric value (0 to 9) of its argument if it is a numeric digit +(that is, if char-numeric? returns #t), or #f on any other character. + +(digit-value #\3) ⟹ 3 +(digit-value #\x0664) ⟹ 4 +(digit-value #\x0AE6) ⟹ 0 +(digit-value #\x0EA6) ⟹ #f + +procedure: (char->integer char) +procedure: (integer->char + +n) + + +Given a Unicode character, char->integer returns an exact integer between 0 and #xD7FF +or between #xE000 and #x10FFFF which is equal to the Unicode scalar value of that +character. Given a non-Unicode character, it returns an exact integer greater than +#x10FFFF. This is true independent of whether the implementation uses the Unicode +representation internally. + +Given an exact integer that is the value returned by a character when char->integer is +applied to it, integer->char returns that character. + +char library procedure: (char-upcase char) +char library procedure: (char-downcase char) +char library procedure: (char-foldcase char) + +The char-upcase procedure, given an argument that is the lowercase part of a Unicode +casing pair, returns the uppercase member of the pair, provided that both characters +are supported by the Scheme implementation. Note that language-sensitive casing pairs +are not used. If the argument is not the lowercase member of such a pair, it is returned. + +The char-downcase procedure, given an argument that is the uppercase part of a +Unicode casing pair, returns the lowercase member of the pair, provided that both +characters are supported by the Scheme implementation. Note that language-sensitive +casing pairs are not used. If the argument is not the uppercase member of such a pair, it +is returned. + +The char-foldcase procedure applies the Unicode simple case-folding algorithm to its +argument and returns the result. Note that language-sensitive folding is not used. If the +character that results from folding is not supported by the implementation, the +argument is returned. See UAX #44 [11] (part of the Unicode Standard) for details. + +Note that many Unicode lowercase characters do not have uppercase equivalents. + +@node Strings +@section Strings + +Strings are sequences of characters. Strings are written as sequences of characters +enclosed within quotation marks ("). Within a string literal, various escape +sequencesrepresent characters other than themselves. Escape sequences always start +with a backslash (\): + +* \a : alarm, U+0007 + +* \b : backspace, U+0008 + +* \t : character tabulation, U+0009 + +* \n : linefeed, U+000A + +* \r : return, U+000D + +* \" : double quote, U+0022 + +* \\ : backslash, U+005C + +* \| : vertical line, U+007C + +* \<intraline whitespace>*<line ending> <intraline whitespace>* : nothing + +* \x<hex scalar value>; : specified character (note the terminating semi-colon). + +The result is unspecified if any other character in a string occurs after a backslash. + +Except for a line ending, any character outside of an escape sequence stands for itself in +the string literal. A line ending which is preceded by \<intraline whitespace> expands to +nothing (along with any trailing intraline whitespace), and can be used to indent strings +for improved legibility. Any other line ending has the same effect as inserting a \n +character into the string. + +Examples: + +"The word \"recursion\" has many meanings." +"Another example:\ntwo lines of text" +"Here's text \ + containing just one line" +"\x03B1; is named GREEK SMALL LETTER ALPHA." The length of a string is the number of +characters that it contains. This number is an exact, non-negative integer that is fixed +when the string is created. The valid indexes of a string are the exact non-negative +integers less than the length of the string. The first character of a string has index 0, the +second has index 1, and so on. + +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 +insensitive”). + +Implementations may forbid certain characters from appearing in strings. However, with +the exception of #\null, ASCII characters must not be forbidden. For example, an +implementation might support the entire Unicode repertoire, but only allow characters +U+0001 to U+00FF (the Latin-1 repertoire without #\null) in strings. + +It is an error to pass such a forbidden character to make-string, string, string-set!, or +string-fill!, as part of the list passed to list->string, or as part of the vector passed to +vector->string (see section 6.8), or in UTF-8 encoded form within a bytevector passed to +utf8->string (see section 6.9). It is also an error for a procedure passed to string-map +(see section 6.10) to return a forbidden character, or for read-string (see section 6.13.2) +to attempt to read one. + +procedure: (string? obj) + +Returns #t if + +obj is a string, otherwise returns #f. + +procedure: (make-string + +k) + + +procedure: (make-string + +k char) + + +The make-string procedure returns a newly allocated string of length + +k. If + +char is given, then all the characters of the string are initialized to + +char, otherwise the contents of the string are unspecified. + +procedure: (string char …) + +Returns a newly allocated string composed of the arguments. It is analogous to list. + +procedure: (string-length string) + +Returns the number of characters in the given + +string. + +procedure: (string-ref string + +k) + + +It is an error if + +k is not a valid index of + +string. + +The string-ref procedure returns character + +k of + +string using zero-origin indexing. + +There is no requirement for this procedure to execute in constant time. + +procedure: (string-set! string k char) + +It is an error if + +k is not a valid index of + +string. + +The string-set! procedure stores + +char in element + +k of + +string. There is no requirement for this procedure to execute in constant time. + +(define (f) (make-string 3 #\*)) +(define (g) "***") +(string-set! (f) 0 #\?) ⟹ unspecified +(string-set! (g) 0 #\?) ⟹ error +(string-set! (symbol->string 'immutable) + 0 + #\?) ⟹ error + +procedure: (string=? + +string1 + +string2 + +string3 …) + + +Returns #t if all the strings are the same length and contain exactly the same characters +in the same positions, otherwise returns #f. + +char library procedure: (string-ci=? + +string1 + +string2 + +string3 …) + + +Returns #t if, after case-folding, all the strings are the same length and contain the same +characters in the same positions, otherwise returns #f. Specifically, these procedures +behave as if string-foldcase were applied to their arguments before comparing them. + +procedure: (string<? + +string1 + +string2 + +string3 …) + + +char library procedure: (string-ci<? + +string1 + +string2 + +string3 …) + + +procedure: (string>? + +string1 + +string2 + +string3 …) + + +char library procedure: (string-ci>? + +string1 + +string2 + +string3 …) + + +procedure: (string<=? + +string1 + +string2 + +string3 …) + + +char library procedure: (string-ci<=? + +string1 + +string2 + +string3 …) + + +procedure: (string>=? + +string1 + +string2 + +string3 …) + + +char library procedure: (string-ci>=? + +string1 + +string2 + +string3 …) + + +These procedures return #t if their arguments are (respectively): monotonically +increasing, monotonically decreasing, monotonically non-decreasing, or monotonically +non-increasing. + +These predicates are required to be transitive. + +These procedures compare strings in an implementation-defined way. One approach is +to make them the lexicographic extensions to strings of the corresponding orderings on +characters. In that case, string<? would be the lexicographic ordering on strings induced +by the ordering char<?​ ​on characters, and if the two strings differ in length but are the +same up to the length of the shorter string, the shorter string would be considered to be +lexicographically less than the longer string. However, it is also permitted to use the +natural ordering imposed by the implementation’s internal representation of strings, or +a more complex locale-specific ordering. + +In all cases, a pair of strings must satisfy exactly one of string<?, string=?, and string>?, +and must satisfy string<=? if and only if they do not satisfy string>? and string>=? if and +only if they do not satisfy string<?. + +The “-ci” procedures behave as if they applied string-foldcase to their arguments before +invoking the corresponding procedures without “-ci”. + +char library procedure: (string-upcase string) +char library procedure: (string-downcase string) +char library procedure: (string-foldcase string) + +These procedures apply the Unicode full string uppercasing, lowercasing, and +case-folding algorithms to their arguments and return the result. In certain cases, the +result differs in length from the argument. If the result is equal to the argument in the +sense of string=?, the argument may be returned. Note that language-sensitive +mappings and foldings are not used. The Unicode Standard prescribes special +treatment of the Greek letter Σ, whose normal lower-case form is σ but which becomes ς +at the end of a word. See UAX #44 [11] (part of the Unicode Standard) for details. +However, implementations of string-downcase are not required to provide this +behavior, and may choose to change Σ to σ in all cases. + +procedure: (substring string start end) + +The substring procedure returns a newly allocated string formed from the characters of + +string beginning with index + +start and ending with index + +end. This is equivalent to calling string-copy with the same arguments, but is provided +for backward compatibility and stylistic flexibility. + +procedure: (string-append + +string …) + + +Returns a newly allocated string whose characters are the concatenation of the +characters in the given strings. + +procedure: (string->list string) +procedure: (string->list string start) +procedure: (string->list string start end) +procedure: (list->string list) + +It is an error if any element of + +list is not a character. + +The string->list procedure returns a newly allocated list of the characters of + +string between + +start and + +end. list->string returns a newly allocated string formed from the elements in the list + +list. In both procedures, order is preserved. string->list and list->string are inverses so +far as equal?​ ​is concerned. + +procedure: (string-copy string) +procedure: (string-copy string start) +procedure: (string-copy string start end) + +Returns a newly allocated copy of the part of the given + +string between + +start and + +end. + +procedure: (string-copy! to at from) +procedure: (string-copy! to at from start) +procedure: (string-copy! to at from start end) + +It is an error if + +at is less than zero or greater than the length of + +to. It is also an error if (- (string-length + +to) + +at) is less than (- + +end + +start). + +Copies the characters of string + +from between + +start and + +end to string + +to, starting at + +at. The order in which characters are copied is unspecified, except that if the source and +destination overlap, copying takes place as if the source is first copied into a temporary +string and then into the destination. This can be achieved without allocating storage by +making sure to copy in the correct direction in such circumstances. + +(define a "12345") +(define b (string-copy "abcde")) +(string-copy! b 1 a 0 2) +b ⟹ "a12de" + +procedure: (string-fill! string fill) +procedure: (string-fill! string fill start) +procedure: (string-fill! string fill start end) + +It is an error if + +fill is not a character. + +The string-fill! procedure stores + +fill in the elements of + +string between + +start and + +end. + +@node Vectors +@section Vectors + +Vectors are heterogeneous structures whose elements are indexed by integers. A vector +typically occupies less space than a list of the same length, and the average time needed +to access a randomly chosen element is typically less for the vector than for the list. + +The length of a vector is the number of elements that it contains. This number is a +non-negative integer that is fixed when the vector is created. The valid indexesof a vector +are the exact non-negative integers less than the length of the vector. The first element +in a vector is indexed by zero, and the last element is indexed by one less than the length +of the vector. + +Vectors are written using the notation #( + +obj …). For example, a vector of length 3 containing the number zero in element 0, the +list (2 2 2 2) in element 1, and the string "Anna" in element 2 can be written as follows: + +#(0 (2 2 2 2) "Anna") Vector constants are self-evaluating, so they do not need to be +quoted in programs. + +procedure: (vector? obj) + +Returns #t if + +obj is a vector; otherwise returns #f. + +procedure: (make-vector k) +procedure: (make-vector k fill) + +Returns a newly allocated vector of + +k elements. If a second argument is given, then each element is initialized to + +fill. Otherwise the initial contents of each element is unspecified. + +procedure: (vector obj …) + +Returns a newly allocated vector whose elements contain the given arguments. It is +analogous to list. + +(vector 'a 'b 'c) ⟹ #(a b c) + +procedure: (vector-length vector) + +Returns the number of elements in + +vector as an exact integer. + +procedure: (vector-ref vector k) + +It is an error if + +k is not a valid index of + +vector. + +The vector-ref procedure returns the contents of element + +k of + +vector. + +(vector-ref '#(1 1 2 3 5 8 13 21) + 5) +⟹ 8 +(vector-ref '#(1 1 2 3 5 8 13 21) + (exact + (round (* 2 (acos -1))))) +⟹ 13 + +procedure: (vector-set! vector k obj) + +It is an error if + +k is not a valid index of + +vector. + +The vector-set! procedure stores + +obj in element + +k of + +vector. + +(let ((vec (vector 0 '(2 2 2 2) "Anna"))) + (vector-set! vec 1 '("Sue" "Sue")) + vec) +⟹ #(0 ("Sue" "Sue") "Anna") + +(vector-set! '#(0 1 2) 1 "doe") +⟹ error ; constant vector + +procedure: (vector->list vector) +procedure: (vector->list vector start) +procedure: (vector->list vector start end) +procedure: (list->vector list) + +The vector->list procedure returns a newly allocated list of the objects contained in the +elements of + +vector between + +start and + +end. The list->vector procedure returns a newly created vector initialized to the elements +of the list + +list. + +In both procedures, order is preserved. + +(vector->list '#(dah dah didah)) +⟹ (dah dah didah) +(vector->list '#(dah dah didah) 1 2) +⟹ (dah) +(list->vector '(dididit dah)) +⟹ #(dididit dah) + +procedure: (vector->string vector) +procedure: (vector->string vector start) +procedure: (vector->string vector start end) +procedure: (string->vector string) +procedure: (string->vector string start) +procedure: (string->vector string start end) + +It is an error if any element of + +vector between + +start and + +end is not a character. + +The vector->string procedure returns a newly allocated string of the objects contained in +the elements of + +vector between + +start and + +end. The string->vector procedure returns a newly created vector initialized to the +elements of the string + +string between + +start and + +end. + +In both procedures, order is preserved. + +(string->vector "ABC") ⟹ #(#\A #\B #\C) +(vector->string + #(#\1 #\2 #\3) ⟹ "123" + +procedure: (vector-copy vector) +procedure: (vector-copy vector start) +procedure: (vector-copy vector start end) + +Returns a newly allocated copy of the elements of the given + +vector between + +start and + +end. The elements of the new vector are the same (in the sense of eqv?) as the elements +of the old. + +(define a #(1 8 2 8)) ; a may be immutable +(define b (vector-copy a)) +(vector-set! b 0 3) ; b is mutable +b ⟹ #(3 8 2 8) +(define c (vector-copy b 1 3)) +c ⟹ #(8 2) + +procedure: (vector-copy! to at from) +procedure: (vector-copy! to at from start) +procedure: (vector-copy! to at from start end) + +It is an error if + +at is less than zero or greater than the length of + +to. It is also an error if (- (vector-length + +to) + +at) is less than (- + +end + +start). + +Copies the elements of vector + +from between + +start and + +end to vector + +to, starting at + +at. The order in which elements are copied is unspecified, except that if the source and +destination overlap, copying takes place as if the source is first copied into a temporary +vector and then into the destination. This can be achieved without allocating storage by +making sure to copy in the correct direction in such circumstances. + +(define a (vector 1 2 3 4 5)) +(define b (vector 10 20 30 40 50)) +(vector-copy! b 1 a 0 2) +b ⟹ #(10 1 2 40 50) + +procedure: (vector-append + +vector …) + + +Returns a newly allocated vector whose elements are the concatenation of the elements +of the given vectors. + +(vector-append #(a b c) #(d e f)) +⟹ #(a b c d e f) + +procedure: (vector-fill! vector fill) +procedure: (vector-fill! vector fill start) +procedure: (vector-fill! vector fill start end) + +The vector-fill! procedure stores + +fill in the elements of + +vector between + +start and + +end. + +(define a (vector 1 2 3 4 5)) +(vector-fill! a 'smash 2 4) +a +⟹ #(1 2 smash smash 5) + +@node Bytevectors +@section Bytevectors + +Bytevectors represent blocks of binary data. They are fixed-length sequences of bytes, +where a byte is an exact integer in the range from 0 to 255 inclusive. A bytevector is +typically more space-efficient than a vector containing the same values. + +The length of a bytevector is the number of elements that it contains. This number is a +non-negative integer that is fixed when the bytevector is created. The valid indexesof a +bytevector are the exact non-negative integers less than the length of the bytevector, +starting at index zero as with vectors. + +Bytevectors are written using the notation #u8( + +byte …). For example, a bytevector of length 3 containing the byte 0 in element 0, the byte +10 in element 1, and the byte 5 in element 2 can be written as follows: + +#u8(0 10 5) Bytevector constants are self-evaluating, so they do not need to be quoted in +programs. + +procedure: (bytevector? obj) + +Returns #t if + +obj is a bytevector. Otherwise, #f is returned. + +procedure: (make-bytevector k) +procedure: (make-bytevector k byte) + +The make-bytevector procedure returns a newly allocated bytevector of length + +k. If + +byte is given, then all elements of the bytevector are initialized to + +byte, otherwise the contents of each element are unspecified. + +(make-bytevector 2 12) ⟹ #u8(12 12) + +procedure: (bytevector + +byte …) + + +Returns a newly allocated bytevector containing its arguments. + +(bytevector 1 3 5 1 3 5) ⟹ #u8(1 3 5 1 3 5) +(bytevector) ⟹ #u8() + +procedure: (bytevector-length bytevector) + +Returns the length of + +bytevector in bytes as an exact integer. + +procedure: (bytevector-u8-ref bytevector k) + +It is an error if + +k is not a valid index of + +bytevector. + +Returns the + +kth byte of + +bytevector. + +(bytevector-u8-ref '#u8(1 1 2 3 5 8 13 21) + 5) +⟹ 8 + +procedure: (bytevector-u8-set! bytevector k byte) + +It is an error if + +k is not a valid index of + +bytevector. + +Stores + +byte as the + +kth byte of + +bytevector. + +(let ((bv (bytevector 1 2 3 4))) + (bytevector-u8-set! bv 1 3) + bv) +⟹ #u8(1 3 3 4) + +procedure: (bytevector-copy bytevector) +procedure: (bytevector-copy bytevector start) +procedure: (bytevector-copy bytevector start end) + +Returns a newly allocated bytevector containing the bytes in + +bytevector between + +start and + +end. + +(define a #u8(1 2 3 4 5)) +(bytevector-copy a 2 4)) ⟹ #u8(3 4) + +procedure: (bytevector-copy! to at from) +procedure: (bytevector-copy! to at from start) +procedure: (bytevector-copy! to at from start end) + +It is an error if + +at is less than zero or greater than the length of + +to. It is also an error if (- (bytevector-length + +to) + +at) is less than (- + +end + +start). + +Copies the bytes of bytevector + +from between + +start and + +end to bytevector + +to, starting at + +at. The order in which bytes are copied is unspecified, except that if the source and +destination overlap, copying takes place as if the source is first copied into a temporary +bytevector and then into the destination. This can be achieved without allocating storage +by making sure to copy in the correct direction in such circumstances. + +(define a (bytevector 1 2 3 4 5)) +(define b (bytevector 10 20 30 40 50)) +(bytevector-copy! b 1 a 0 2) +b ⟹ #u8(10 1 2 40 50) + + Note: This procedure appears in R6RS, but places the source before the destination, + contrary to other such procedures in Scheme. + +procedure: (bytevector-append + +bytevector …) + + +Returns a newly allocated bytevector whose elements are the concatenation of the +elements in the given bytevectors. + +(bytevector-append #u8(0 1 2) #u8(3 4 5)) +⟹ #u8(0 1 2 3 4 5) + +procedure: (utf8->string bytevector) +procedure: (utf8->string bytevector start) +procedure: (utf8->string bytevector start end) +procedure: (string->utf8 string) +procedure: (string->utf8 string start) +procedure: (string->utf8 string start end) + +It is an error for + +bytevector to contain invalid UTF-8 byte sequences. + +These procedures translate between strings and bytevectors that encode those strings +using the UTF-8 encoding. The utf8->string procedure decodes the bytes of a bytevector +between + +start and + +end and returns the corresponding string; the string->utf8 procedure encodes the +characters of a string between + +start and + +end and returns the corresponding bytevector. + +(utf8->string #u8(#x41)) ⟹ "A" +(string->utf8 "λ") ⟹ #u8(#xCE #xBB) + +@node Control features +@section Control features + +This section describes various primitive procedures which control the flow of program +execution in special ways. Procedures in this section that invoke procedure arguments +always do so in the same dynamic environment as the call of the original procedure. The +procedure?​ ​predicate is also described here. + +procedure: (procedure? obj) + +Returns #t if + +obj is a procedure, otherwise returns #f. + +(procedure? car) ⟹ #t +(procedure? 'car) ⟹ #f +(procedure? (lambda (x) (* x x))) + ⟹ #t +(procedure? '(lambda (x) (* x x))) + ⟹ #f +(call-with-current-continuation procedure?) + ⟹ #t + +procedure: (apply proc + +arg1 … args) + + +The apply procedure calls + +proc with the elements of the list (append (list + +arg1 …) + +args) as the actual arguments. + +(apply + (list 3 4)) ⟹ 7 + +(define compose + (lambda (f g) + (lambda args + (f (apply g args))))) + +((compose sqrt *) 12 75) ⟹ 30 + +procedure: (map proc + +list1 + +list2 …) + + +It is an error if + +proc does not accept as many arguments as there are lists and return a single value. + +The map procedure applies + +proc element-wise to the elements of the + +lists and returns a list of the results, in order. If more than one + +list is given and not all lists have the same length, map terminates when the shortest list +runs out. The + +lists can be circular, but it is an error if all of them are circular. It is an error for + +proc to mutate any of the lists. The dynamic order in which + +proc is applied to the elements of the + +lists is unspecified. If multiple returns occur from map, the values returned by earlier +returns are not mutated. + +(map cadr '((a b) (d e) (g h))) +⟹ (b e h) + +(map (lambda (n) (expt n n)) + '(1 2 3 4 5)) +⟹ (1 4 27 256 3125) + +(map + '(1 2 3) '(4 5 6 7)) ⟹ (5 7 9) + +(let ((count 0)) + (map (lambda (ignored) + (set! count (+ count 1)) + count) + '(a b))) ⟹ (1 2) + +or (2 1) + +procedure: (string-map proc + +string1 + +string2 …) + + +It is an error if + +proc does not accept as many arguments as there are strings and return a single +character. + +The string-map procedure applies + +proc element-wise to the elements of the + +strings and returns a string of the results, in order. If more than one + +string is given and not all strings have the same length, string-map terminates when the +shortest string runs out. The dynamic order in which + +proc is applied to the elements of the + +strings is unspecified. If multiple returns occur from string-map, the values returned by +earlier returns are not mutated. + +(string-map char-foldcase "AbdEgH") +⟹ "abdegh" + +(string-map + (lambda (c) + (integer->char (+ 1 (char->integer c)))) + "HAL") +⟹ "IBM" + +(string-map + (lambda (c k) + ((if (eqv? k #\u) char-upcase char-downcase) + c)) + "studlycaps xxx" + "ululululul") +⟹ "StUdLyCaPs" + +procedure: (vector-map proc + +vector1 + +vector2 …) + + +It is an error if + +proc does not accept as many arguments as there are vectors and return a single value. + +The vector-map procedure applies + +proc element-wise to the elements of the + +vectors and returns a vector of the results, in order. If more than one + +vector is given and not all vectors have the same length, vector-map terminates when the +shortest vector runs out. The dynamic order in which + +proc is applied to the elements of the + +vectors is unspecified. If multiple returns occur from vector-map, the values returned by +earlier returns are not mutated. + +(vector-map cadr '#((a b) (d e) (g h))) +⟹ #(b e h) + +(vector-map (lambda (n) (expt n n)) + '#(1 2 3 4 5)) +⟹ #(1 4 27 256 3125) + +(vector-map + '#(1 2 3) '#(4 5 6 7)) +⟹ #(5 7 9) + +(let ((count 0)) + (vector-map + (lambda (ignored) + (set! count (+ count 1)) + count) + '#(a b))) ⟹ #(1 2) + +or #(2 1) + +procedure: (for-each proc + +list1 + +list2 …) + + +It is an error if + +proc does not accept as many arguments as there are lists. + +The arguments to for-each are like the arguments to map, but for-each calls + +proc for its side effects rather than for its values. Unlike map, for-each is guaranteed to +call + +proc on the elements of the + +lists in order from the first element(s) to the last, and the value returned by for-each is +unspecified. If more than one + +list is given and not all lists have the same length, for-each terminates when the shortest +list runs out. The + +lists can be circular, but it is an error if all of them are circular. + +It is an error for + +proc to mutate any of the lists. + +(let ((v (make-vector 5))) + (for-each (lambda (i) + (vector-set! v i (* i i))) + '(0 1 2 3 4)) + v) ⟹ #(0 1 4 9 16) + +procedure: (string-for-each proc + +string1 + +string2 …) + + +It is an error if + +proc does not accept as many arguments as there are strings. + +The arguments to string-for-each are like the arguments to string-map, but +string-for-each calls + +proc for its side effects rather than for its values. Unlike string-map, string-for-each is +guaranteed to call + +proc on the elements of the + +strings in order from the first element(s) to the last, and the value returned by +string-for-each is unspecified. If more than one + +string is given and not all strings have the same length, string-for-each terminates when +the shortest string runs out. It is an error for + +proc to mutate any of the strings. + +(let ((v '())) + (string-for-each + (lambda (c) (set! v (cons (char->integer c) v))) + "abcde") + v) ⟹ (101 100 99 98 97) + +procedure: (vector-for-each proc + +vector1 + +vector2 …) + + +It is an error if + +proc does not accept as many arguments as there are vectors. + +The arguments to vector-for-each are like the arguments to vector-map, but +vector-for-each calls + +proc for its side effects rather than for its values. Unlike vector-map, vector-for-each is +guaranteed to call + +proc on the elements of the + +vectors in order from the first element(s) to the last, and the value returned by +vector-for-each is unspecified. If more than one + +vector is given and not all vectors have the same length, vector-for-each terminates when +the shortest vector runs out. It is an error for + +proc to mutate any of the vectors. + +(let ((v (make-list 5))) + (vector-for-each + (lambda (i) (list-set! v i (* i i))) + '#(0 1 2 3 4)) + v) ⟹ (0 1 4 9 16) + +procedure: (call-with-current-continuation proc) +procedure: (call/cc proc) + +It is an error if + +proc does not accept one argument. + +The procedure call-with-current-continuation (or its equivalent abbreviation call/cc) +packages the current continuation (see the rationale below) as an “escape +procedure”and passes it as an argument to + +proc. The escape procedure is a Scheme procedure that, if it is later called, will abandon +whatever continuation is in effect at that later time and will instead use the continuation +that was in effect when the escape procedure was created. Calling the escape procedure +will cause the invocation of + +before and + +after thunks installed using dynamic-wind. + +The escape procedure accepts the same number of arguments as the continuation to +the original call to call-with-current-continuation. Most continuations take only one +value. Continuations created by the call-with-values procedure (including the initialization +expressions of define-values, let-values, and let*-values expressions), take the number +of values that the consumer expects. The continuations of all non-final expressions +within a sequence of expressions, such as in lambda, case-lambda, begin, let, let*, letrec, +letrec*, let-values, let*-values, let-syntax, letrec-syntax, parameterize, guard, case, cond, +when, and unless expressions, take an arbitrary number of values because they discard +the values passed to them in any event. The effect of passing no values or more than one +value to continuations that were not created in one of these ways is unspecified. + +The escape procedure that is passed to + +proc has unlimited extent just like any other procedure in Scheme. It can be stored in +variables or data structures and can be called as many times as desired. However, like +the raise and error procedures, it never returns to its caller. + +The following examples show only the simplest ways in which +call-with-current-continuation is used. If all real uses were as simple as these examples, +there would be no need for a procedure with the power of +call-with-current-continuation. + +(call-with-current-continuation + (lambda (exit) + (for-each (lambda (x) + (if (negative? x) + (exit x))) + '(54 0 37 -3 245 19)) + #t)) ⟹ -3 + +(define list-length + (lambda (obj) + (call-with-current-continuation + (lambda (return) + (letrec ((r + (lambda (obj) + (cond ((null? obj) 0) + ((pair? obj) + (+ (r (cdr obj)) 1)) + (else (return #f)))))) + (r obj)))))) + +(list-length '(1 2 3 4)) ⟹ 4 + +(list-length '(a b . c)) ⟹ #f + + Rationale: A common use of call-with-current-continuation is for structured, + non-local exits from loops or procedure bodies, but in fact + call-with-current-continuation is useful for implementing a wide variety of advanced + control structures. In fact, raise and guard provide a more structured mechanism + for non-local exits. + + Whenever a Scheme expression is evaluated there is a continuation wanting the + result of the expression. The continuation represents an entire (default) future for + the computation. If the expression is evaluated at the REPL, for example, then the + continuation might take the result, print it on the screen, prompt for the next input, + evaluate it, and so on forever. Most of the time the continuation includes actions + specified by user code, as in a continuation that will take the result, multiply it by the + value stored in a local variable, add seven, and give the answer to the REPL’s + continuation to be printed. Normally these ubiquitous continuations are hidden + behind the scenes and programmers do not think much about them. On rare + occasions, however, a programmer needs to deal with continuations explicitly. The + call-with-current-continuation procedure allows Scheme programmers to do that + by creating a procedure that acts just like the current continuation. + +procedure: (values obj …) + +Delivers all of its arguments to its continuation. The values procedure might be defined +as follows: + +(define (values . things) + (call-with-current-continuation + (lambda (cont) (apply cont things)))) + +procedure: (call-with-values producer consumer) + +Calls its + +producer argument with no arguments and a continuation that, when passed some +values, calls the + +consumer procedure with those values as arguments. The continuation for the call to + +consumer is the continuation of the call to call-with-values. + +(call-with-values (lambda () (values 4 5)) + (lambda (a b) b)) + ⟹ 5 + +(call-with-values * -) ⟹ -1 + +procedure: (dynamic-wind before thunk after) + +Calls + +thunk without arguments, returning the result(s) of this call. + +Before and + +after are called, also without arguments, as required by the following rules. Note that, in +the absence of calls to continuations captured using call-with-current-continuation, the +three arguments are called once each, in order. + +Before is called whenever execution enters the dynamic extent of the call to + +thunk and + +after is called whenever it exits that dynamic extent. The dynamic extent of a procedure +call is the period between when the call is initiated and when it returns. The + +before and + +after thunks are called in the same dynamic environment as the call to dynamic-wind. In +Scheme, because of call-with-current-continuation, the dynamic extent of a call is not +always a single, connected time period. It is defined as follows: + +* The dynamic extent is entered when execution of the body of the called procedure + begins. + +* The dynamic extent is also entered when execution is not within the dynamic extent + and a continuation is invoked that was captured (using call-with-current-continuation) + during the dynamic extent. + +* It is exited when the called procedure returns. + +* It is also exited when execution is within the dynamic extent and a continuation is + invoked that was captured while not within the dynamic extent. + +If a second call to dynamic-wind occurs within the dynamic extent of the call to + +thunk and then a continuation is invoked in such a way that the + +afters from these two invocations of dynamic-wind are both to be called, then the + +after associated with the second (inner) call to dynamic-wind is called first. + +If a second call to dynamic-wind occurs within the dynamic extent of the call to + +thunk and then a continuation is invoked in such a way that the + +befores from these two invocations of dynamic-wind are both to be called, then the + +before associated with the first (outer) call to dynamic-wind is called first. + +If invoking a continuation requires calling the + +before from one call to dynamic-wind and the + +after from another, then the + +after is called first. + +The effect of using a captured continuation to enter or exit the dynamic extent of a call +to + +before or + +after is unspecified. + +(let ((path '()) + (c #f)) + (let ((add (lambda (s) + (set! path (cons s path))))) + (dynamic-wind + (lambda () (add 'connect)) + (lambda () + (add (call-with-current-continuation + (lambda (c0) + (set! c c0) + 'talk1)))) + (lambda () (add 'disconnect))) + (if (< (length path) 4) + (c 'talk2) + (reverse path)))) + +⟹ (connect talk1 disconnect + connect talk2 disconnect) + +@node Exceptions +@section Exceptions + +This section describes Scheme’s exception-handling and exception-raising procedures. +For the concept of Scheme exceptions, see section 1.3.2. See also 4.2.7 for the guard +syntax. + +Exception handlers are one-argument procedures that determine the action the program +takes when an exceptional situation is signaled. The system implicitly maintains a +current exception handler in the dynamic environment. + +The program raises an exception by invoking the current exception handler, passing it an +object encapsulating information about the exception. Any procedure accepting one +argument can serve as an exception handler and any object can be used to represent an +exception. + +procedure: (with-exception-handler + +handler + +thunk) + + +It is an error if + +handler does not accept one argument. It is also an error if + +thunk does not accept zero arguments. + +The with-exception-handler procedure returns the results of invoking + +thunk. + +Handler is installed as the current exception handler in the dynamic environment used +for the invocation of + +thunk. + +(call-with-current-continuation + (lambda (k) + (with-exception-handler + (lambda (x) + (display "condition: ") + (write x) + (newline) + (k 'exception)) + (lambda () + (+ 1 (raise 'an-error)))))) + ⟹ exception + and prints condition: an-error + +(with-exception-handler + (lambda (x) + (display "something went wrong\n")) + (lambda () + (+ 1 (raise 'an-error)))) + prints something went wrong After printing, the second example then raises another +exception. + +procedure: (raise + +obj) + + +Raises an exception by invoking the current exception handler 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 the handler +being called was installed. If the handler returns, a secondary exception is raised in the +same dynamic environment as the handler. The relationship between + +obj and the object raised by the secondary exception is unspecified. + +procedure: (raise-continuable + +obj) + + +Raises an exception by invoking the current exception handler on + +obj. The handler is called with the same dynamic environment as the call to +raise-continuable, except that: (1) the current exception handler is the one that was in +place when the handler being called was installed, and (2) if the handler being called +returns, then it will again become the current exception handler. If the handler returns, +the values it returns become the values returned by the call to raise-continuable. + +(with-exception-handler + (lambda (con) + (cond + ((string? con) + (display con)) + (else + (display "a warning has been issued"))) + 42) + (lambda () + (+ (raise-continuable "should be a number") + 23))) + prints: should be a number + ⟹ 65 + +procedure: (error + +message + +obj …) + + +Message should be a string. + +Raises an exception as if by calling raise on a newly allocated implementation-defined +object which encapsulates the information provided by + +message, as well as any + +objs, known as the irritants. The procedure error-object? must return #t on such objects. + +(define (null-list? l) + (cond ((pair? l) #f) + ((null? l) #t) + (else + (error + "null-list?: argument out of domain" + l)))) + +procedure: (error-object? obj) + +Returns #t if + +obj is an object created by error or one of an implementation-defined set of objects. +Otherwise, it returns #f. The objects used to signal errors, including those which satisfy +the predicates file-error? and read-error?, may or may not satisfy error-object?. + +procedure: (error-object-message error-object) + +Returns the message encapsulated by + +error-object. + +procedure: (error-object-irritants error-object) + +Returns a list of the irritants encapsulated by + +error-object. + +procedure: (read-error? obj) +procedure: (file-error? obj) + +Error type predicates. Returns #t if + +obj is an object raised by the read procedure or by the inability to open an input or +output port on a file, respectively. Otherwise, it returns #f. + +@node Environments and evaluation +@section Environments and evaluation + +eval library procedure: (environment + +list1 …) + + +This procedure returns a specifier for the environment that results by starting with an +empty environment and then importing each + +list, considered as an import set, into it. (See section 5.6 for a description of import sets.) +The bindings of the environment represented by the specifier are immutable, as is the +environment itself. + +r5rs library procedure: (scheme-report-environment version) + +If + +version is equal to 5, corresponding to R5RS, scheme-report-environment returns a +specifier for an environment that contains only the bindings defined in the R5RS​ ​library. +Implementations must support this value of + +version. + +Implementations may also support other values of + +version, in which case they return a specifier for an environment containing bindings +corresponding to the specified version of the report. If + +version is neither 5 nor another value supported by the implementation, an error is +signaled. + +The effect of defining or assigning (through the use of eval) an identifier bound in a +scheme-report-environment (for example car) is unspecified. Thus both the +environment and the bindings it contains may be immutable. + +r5rs library procedure: (null-environment version) + +If + +version is equal to 5, corresponding to R5RS, the null-environment procedure returns a +specifier for an environment that contains only the bindings for all syntactic keywords +defined in the R5RS​ ​library. Implementations must support this value of + +version. + +Implementations may also support other values of + +version, in which case they return a specifier for an environment containing appropriate +bindings corresponding to the specified version of the report. If + +version is neither 5 nor another value supported by the implementation, an error is +signaled. + +The effect of defining or assigning (through the use of eval) an identifier bound in a +scheme-report-environment (for example car) is unspecified. Thus both the +environment and the bindings it contains may be immutable. + +repl library procedure: (interaction-environment) + +This procedure returns a specifier for a mutable environment that contains an +implementation-defined set of bindings, typically a superset of those exported by +(scheme base). The intent is that this procedure will return the environment in which the +implementation would evaluate expressions entered by the user into a REPL. + +eval library procedure: (eval expr-or-def environment-specifier) + +If + +expr-or-def is an expression, it is evaluated in the specified environment and its values are +returned. If it is a definition, the specified identifier(s) are defined in the specified +environment, provided the environment is not immutable. Implementations may extend +eval to allow other objects. + +(eval '(* 7 3) (environment '(scheme base))) + ⟹ 21 + +(let ((f (eval '(lambda (f x) (f x x)) + (null-environment 5)))) + (f + 10)) + ⟹ 20 +(eval '(define foo 32) + (environment '(scheme base))) + ⟹ error is signaled + +@node Input and output +@section Input and output + +@node Ports +@subsection Ports + +Ports represent input and output devices. To Scheme, an input port is a Scheme object +that can deliver data upon command, while an output port is a Scheme object that can +accept data.Whether the input and output port types are disjoint is +implementation-dependent. + +Different port types operate on different data. Scheme implementations are required to +support textual ports and binary ports, but may also provide other port types. + +A textual port supports reading or writing of individual characters from or to a backing +store containing characters using read-char and write-char below, and it supports +operations defined in terms of characters, such as read and write. + +A binary port supports reading or writing of individual bytes from or to a backing store +containing bytes using read-u8 and write-u8 below, as well as operations defined in +terms of bytes. Whether the textual and binary port types are disjoint is +implementation-dependent. + +Ports can be used to access files, devices, and similar things on the host system on which +the Scheme program is running. + +procedure: (call-with-port port proc) + +It is an error if + +proc does not accept one argument. + +The call-with-port procedure calls + +proc with + +port as an argument. If + +proc returns, then the port is closed automatically and the values yielded by the + +proc are returned. If + +proc does not return, then the port must not be closed automatically unless it is possible +to prove that the port will never again be used for a read or write operation. + + Rationale: Because Scheme’s escape procedures have unlimited extent, it is possible + to escape from the current continuation but later to resume it. If implementations + were permitted to close the port on any escape from the current continuation, then + it would be impossible to write portable code using both + call-with-current-continuation and call-with-port. + +file library procedure: (call-with-input-file string proc) +file library procedure: (call-with-output-file string proc) + +It is an error if + +proc does not accept one argument. + +These procedures obtain a textual port obtained by opening the named file for input or +output as if by open-input-file or open-output-file. The port and + +proc are then passed to a procedure equivalent to call-with-port. + +procedure: (input-port? obj) +procedure: (output-port? obj) +procedure: (textual-port? obj) +procedure: (binary-port? obj) +procedure: (port? obj) + +These procedures return #t if + +obj is an input port, output port, textual port, binary port, or any kind of port, +respectively. Otherwise they return #f. + +procedure: (input-port-open? port) +procedure: (output-port-open? port) + +Returns #t if + +port is still open and capable of performing input or output, respectively, and #f +otherwise. + +procedure: (current-input-port) +procedure: (current-output-port) +procedure: (current-error-port) + +Returns the current default input port, output port, or error port (an output port), +respectively. These procedures are parameter objects, which can be overridden with +parameterize (see section 4.2.6). The initial bindings for these are +implementation-defined textual ports. + +file library procedure: (with-input-from-file string thunk) +file library procedure: (with-output-to-file string thunk) + +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 or current-output-port +(as used by (read), (write + +obj), and so forth). The + +thunk is then called with no arguments. When the + +thunk returns, the port is closed and the previous default is restored. It is an error if + +thunk does not accept zero arguments. Both procedures return the values yielded by + +thunk. If an escape procedure is used to escape from the continuation of these +procedures, they behave exactly as if the current input or output port had been bound +dynamically with parameterize. + +file library procedure: (open-input-file string) +file library procedure: (open-binary-input-file string) + +Takes a + +string for an existing file and returns a textual input port or binary input port that is +capable of delivering data from the file. If the file does not exist or cannot be opened, an +error that satisfies file-error? is signaled. + +file library procedure: (open-output-file string) +file library procedure: (open-binary-output-file string) + +Takes a + +string naming an output file to be created and returns a textual output port or binary +output port that is capable of writing data to a new file by that name. If a file with the +given name already exists, the effect is unspecified. If the file cannot be opened, an error +that satisfies file-error? is signaled. + +procedure: (close-port port) +procedure: (close-input-port port) +procedure: (close-output-port port) + +Closes the resource associated with + +port, rendering the + +port incapable of delivering or accepting data. It is an error to apply the last two +procedures to a port which is not an input or output port, respectively. Scheme +implementations may provide ports which are simultaneously input 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. + +These routines have no effect if the port has already been closed. + +procedure: (open-input-string string) + +Takes a string and returns a textual input port that delivers characters from the string. If +the string is modified, the effect is unspecified. + +procedure: (open-output-string) + +Returns a textual output port that will accumulate characters for retrieval by +get-output-string. + +procedure: (get-output-string port) + +It is an error if + +port was not created with open-output-string. + +Returns a string consisting of the characters that have been output to the port so far in +the order they were output. If the result string is modified, the effect is unspecified. + +(parameterize + ((current-output-port + (open-output-string))) + (display "piece") + (display " by piece ") + (display "by piece.") + (newline) + (get-output-string (current-output-port))) + +⟹ "piece by piece by piece.\n" + +procedure: (open-input-bytevector bytevector) + +Takes a bytevector and returns a binary input port that delivers bytes from the +bytevector. + +procedure: (open-output-bytevector) + +Returns a binary output port that will accumulate bytes for retrieval by +get-output-bytevector. + +procedure: (get-output-bytevector port) + +It is an error if + +port was not created with open-output-bytevector. + +Returns a bytevector consisting of the bytes that have been output to the port so far in +the order they were output. + +@node Input +@subsection Input + +If + +port is omitted from any input procedure, it defaults to the value returned by +(current-input-port). It is an error to attempt an input operation on a closed port. + +read library procedure: (read) +read library procedure: (read port) + +The read procedure converts external representations of Scheme objects into the +objects themselves. That is, it is a parser for the non-terminal <datum> (see sections +7.1.2 and 6.4). It returns the next object parsable from the given textual input + +port, updating + +port to point to the first character past the end of the external representation of the +object. + +Implementations may support extended syntax to represent record types or other types +that do not have datum representations. + +If an end of file is encountered in the input before any characters are found that can +begin an object, then an end-of-file object is returned. The port remains open, and +further attempts to read will also return an end-of-file object. If an end of file is +encountered after the beginning of an object’s external representation, but the external +representation is incomplete and therefore not parsable, an error that satisfies +read-error? is signaled. + +procedure: (read-char) +procedure: (read-char port) + +Returns the next character available from the textual input + +port, updating the + +port to point to the following character. If no more characters are available, an end-of-file +object is returned. + +procedure: (peek-char) +procedure: (peek-char port) + +Returns the next character available from the textual input + +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. + + 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 with the same + + port. The only difference is that the very next call to read-char or peek-char on that + + port will return the value returned by the preceding call to peek-char. In particular, a + call to peek-char on an interactive port will hang waiting for input whenever a call to + read-char would have hung. + +procedure: (read-line) +procedure: (read-line port) + +Returns the next line of text available from the textual input + +port, updating the + +port to point to the following 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 returned, and the port is updated to +point just past the end of line. If an end of file is encountered before any end of line is +read, but some characters have been read, a string containing those characters is +returned. If an end of file is encountered before any characters are read, an end-of-file +object is returned. For the purpose of this procedure, an end of line consists of either a +linefeed character, a carriage return character, or a sequence of a carriage return +character followed by a linefeed character. Implementations may also recognize other +end of line characters or sequences. + +procedure: (eof-object? obj) + +Returns #t if + +obj is an end-of-file object, otherwise returns #f. The precise set of end-of-file objects +will vary among implementations, but in any case no end-of-file object will ever be an +object that can be read in using read. + +procedure: (eof-object) + +Returns an end-of-file object, not necessarily unique. + +procedure: (char-ready?) +procedure: (char-ready? port) + +Returns #t if a character is ready on the textual input + +port and returns #f otherwise. If char-ready returns #t then the next read-char operation +on the given + +port is guaranteed not to hang. If the + +port is at end of file then char-ready? returns #t. + + Rationale: The char-ready? procedure exists to make it possible for a program to + accept characters from interactive ports without getting stuck waiting for input. + Any input editors associated with such ports must ensure that characters whose + existence has been asserted by char-ready?​ ​cannot be removed 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 interactive port that has no ready characters. + +procedure: (read-string k) +procedure: (read-string k port) + +Reads the next + +k characters, or as many as are available before the end of file, from the textual input + +port into a newly allocated string in left-to-right order and returns the string. If no +characters are available before the end of file, an end-of-file object is returned. + +procedure: (read-u8) +procedure: (read-u8 port) + +Returns the next byte available from the binary input + +port, updating the + +port to point to the following byte. If no more bytes are available, an end-of-file object is +returned. + +procedure: (peek-u8) +procedure: (peek-u8 port) + +Returns the next byte available from the binary input + +port, but without updating the + +port to point to the following byte. If no more bytes are available, an end-of-file object is +returned. + +procedure: (u8-ready?) +procedure: (u8-ready? port) + +Returns #t if a byte is ready on the binary input + +port and returns #f otherwise. If u8-ready? returns #t then the next read-u8 operation on +the given + +port is guaranteed not to hang. If the + +port is at end of file then u8-ready?​ ​returns #t. + +procedure: (read-bytevector k) +procedure: (read-bytevector k port) + +Reads the next + +k bytes, or as many as are available before the end of file, from the binary input + +port into a newly allocated bytevector in left-to-right order and returns the bytevector. If +no bytes are available before the end of file, an end-of-file object is returned. + +procedure: (read-bytevector! bytevector) +procedure: (read-bytevector! bytevector port) +procedure: (read-bytevector! bytevector port start) +procedure: (read-bytevector! bytevector port start end) + +Reads the next end − start bytes, or as many as are available before the end of file, from +the binary input + +port into + +bytevector in left-to-right order beginning at the + +start position. If + +end is not supplied, reads until the end of + +bytevector has been reached. If + +start is not supplied, reads beginning at position 0. Returns the number of bytes read. If +no bytes are available, an end-of-file object is returned. + +@node Output +@subsection Output + +If + +port is omitted from any output procedure, it defaults to the value returned by +(current-output-port). It is an error to attempt an output operation on a closed port. + +write library procedure: (write obj) +write library procedure: (write obj port) + +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 backslash and quotation mark characters are escaped by +backslashes. Symbols that contain non-ASCII characters are escaped with vertical lines. +Character objects are written using the #\ notation. + +If + +obj contains cycles which would cause an infinite loop using the normal written +representation, then at least the objects that form part of the cycle must be represented +using datum labels as described in section 2.4. Datum labels must not be used if there +are no cycles. + +Implementations may support extended syntax to represent record types or other types +that do not have datum representations. + +The write procedure returns an unspecified value. + +write library procedure: (write-shared obj) +write library procedure: (write-shared obj port) + +The write-shared procedure is the same as write, except that shared structure must be +represented using datum labels for all pairs and vectors that appear more than once in +the output. + +write library procedure: (write-simple obj) +write library procedure: (write-simple obj port) + +The write-simple procedure is the same as write, except that shared structure is never +represented using datum labels. This can cause write-simple not to terminate if + +obj contains circular structure. + +write library procedure: (display obj) +write library procedure: (display obj port) + +Writes a representation of + +obj to the given textual output + +port. Strings that appear in the written representation are output as if by write-string +instead of by write. Symbols are not escaped. Character objects appear in the +representation as if written by write-char instead of by write. + +The display representation of other objects is unspecified. However, display must not +loop forever on self-referencing pairs, vectors, or records. Thus if the normal write +representation is used, datum labels are needed to represent cycles as in write. + +Implementations may support extended syntax to represent record types or other types +that do not have datum representations. + +The display procedure returns an unspecified value. + + Rationale: The write procedure is intended for producing machine-readable output + and display for producing human-readable output. + +procedure: (newline) +procedure: (newline port) + +Writes an end of line to textual output + +port. Exactly how this is done differs from one operating system to another. Returns an +unspecified value. + +procedure: (write-char char) +procedure: (write-char char port) + +Writes the character + +char (not an external representation of the character) to the given textual output + +port and returns an unspecified value. + +procedure: (write-string string) +procedure: (write-string string port) +procedure: (write-string string port start) +procedure: (write-string string port start end) + +Writes the characters of + +string from + +start to + +end in left-to-right order to the textual output + +port. + +procedure: (write-u8 byte) +procedure: (write-u8 byte port) + +Writes the + +byte to the given binary output + +port and returns an unspecified value. + +procedure: (write-bytevector bytevector) +procedure: (write-bytevector bytevector port) +procedure: (write-bytevector bytevector port start) +procedure: (write-bytevector bytevector port start end) + +Writes the bytes of + +bytevector from + +start to + +end in left-to-right order to the binary output + +port. + +procedure: (flush-output-port) +procedure: (flush-output-port port) + +Flushes any buffered output from the buffer of output-port to the underlying file or +device and returns an unspecified value. + +@node System interface +@section System interface + +Questions of system interface generally fall outside of the domain of this report. +However, the following operations are important enough to deserve description here. + +load library procedure: (load filename) +load library procedure: (load filename environment-specifier) + +It is an error if + +filename is not a string. + +An implementation-dependent operation is used to transform + +filename into the name of an existing file containing Scheme source code. The load +procedure reads expressions and definitions from the file and evaluates them +sequentially in the environment specified by + +environment-specifier. If + +environment-specifier is omitted, (interaction-environment) is assumed. + +It is unspecified whether the results of the expressions are printed. The load procedure +does not affect the values returned by current-input-port and current-output-port. It +returns an unspecified value. + + Rationale: For portability, load must operate on source files. Its operation on other + kinds of files necessarily varies among implementations. + +file library procedure: (file-exists? filename) + +It is an error if + +filename is not a string. + +The file-exists? procedure returns #t if the named file exists at the time the procedure is +called, and #f otherwise. + +file library procedure: (delete-file filename) + +It is an error if + +filename is not a string. + +The delete-file procedure deletes the named file if it exists and can be deleted, and +returns an unspecified value. If the file does not exist or cannot be deleted, an error that +satisfies file-error? is signaled. + +process-context library procedure: (command-line) + +Returns the command line passed to the process as a list of strings. The first string +corresponds to the command name, and is implementation-dependent. It is an error to +mutate any of these strings. + +process-context library procedure: (exit) +process-context library procedure: (exit obj) + +Runs all outstanding dynamic-wind + +after procedures, terminates the running program, and communicates an exit value to +the operating system. If no argument is supplied, or if + +obj is #t, the exit procedure should communicate 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. Otherwise, exit should translate + +obj into an appropriate exit value for the operating system, if possible. + +The exit procedure must not signal an exception or return to its continuation. + + Note: Because of the requirement to run handlers, this procedure is not just the + operating system’s exit procedure. + +process-context library procedure: (emergency-exit) +process-context library procedure: (emergency-exit obj) + +Terminates the program without running any outstanding dynamic-wind + +after procedures and communicates an exit value to the operating system in the same +manner as exit. + + Note: The emergency-exit procedure corresponds to the _exit procedure in Windows + and Posix. + +process-context library procedure: (get-environment-variable name) + +Many operating systems provide each running process with an environment consisting of +environment variables. (This environment is not to be confused with the Scheme +environments that can be passed to eval: see section 6.12.) Both the name and value of +an environment variable are strings. The procedure get-environment-variable returns +the value of the environment variable + +name, or #f if the named environment variable is not found. It may use locale information +to encode the name and decode the value of the environment variable. It is an error if +get-environment-variable can’t decode the value. It is also an error to mutate the +resulting string. + +(get-environment-variable "PATH") +⟹ "/usr/local/bin:/usr/bin:/bin" + +process-context library procedure: (get-environment-variables) + +Returns the names and values of all the environment variables as an alist, where the car +of each entry is the name of an environment variable and the cdr is its value, both as +strings. The order of the list is unspecified. It is an error to mutate any of these strings +or the alist itself. + +(get-environment-variables) +⟹ (("USER" . "root") ("HOME" . "/")) + +time library procedure: (current-second) + +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 (equivalent to +8.000082 seconds before midnight Universal Time) and the value 1.0 represents one TAI +second later. Neither high accuracy nor high precision are required; in particular, +returning Coordinated Universal Time plus a suitable constant might be the best an +implementation can do. + +As of 2018, a TAI-UTC offset table can be found at [40]. + +time library procedure: (current-jiffy) + +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 force many implementations to return + integers which have to be allocated for most calls, rendering current-jiffy less + useful for accurate timing measurements. + +time library procedure: (jiffies-per-second) + +Returns an exact integer representing the number of jiffies per SI second. This value is +an implementation-specified constant. + +(define (time-length) + (let ((list (make-list 100000)) + (start (current-jiffy))) + (length list) + (/ (- (current-jiffy) start) + (jiffies-per-second)))) + +procedure: (features) + +Returns a list of the feature identifiers which cond-expand treats as true. It is an error to +modify this list. Here is an example of what features might return: + +(features) ⟹ + (r7rs ratios exact-complex full-unicode + gnu-linux little-endian + fantastic-scheme + fantastic-scheme-1.0 + space-ship-control-system) @node Formal syntax and semantics @chapter Formal syntax and semantics