Revised7 Report on the Algorithmic Language Scheme
The Valued Fascicle

draft

Editor's introduction to this fascicle

This section will not appear in the final report.

The Revised7 Report on the Algorithmic Language Scheme, Large Edition, is released in fascicles, which are incremental releases of the full standard.

This is the Valued Fascicle (fascicle 3 of 8) containing the description of the values that make up Scheme data, such as pairs, vectors, numbers, and strings.

Changes to the R7RS

The major features of this fascicle:

What Implementations Need To Do To Support These Changes

Raw string literals will require changes to the reader. Some standard library procedures need redefinition.

Editorial conventions

The phrase it is an error as traditionally used in Scheme reports has been retired in this fascicle. In its place we have adopted a three-way distinction between requirements on implementations, which should be familiar from the specifications of other languages including Common Lisp and C.

As in the R7RS-Small, the phrase an error is signalled continues to refer to a situation in which an exception is required to be raised.

The R7RS-Large Foundations will incorporate a revised version of the R6RS condition types which is compatible with the error objects defined by the small language report, but this is not yet specified and will be included in a future fascicle. However, the phrase it is a syntax violation or a syntax violation is signalled means that an exception is raised with condition type &syntax as in the R6RS.

The phrase domain error (or it is a domain error) refers to using a procedure with an argument value which is outside the specified range of possible values for that argument. It is not yet specified what concrete action implementations should take in this case in the R7RS-Large Foundations. Preliminarily, implementations are encouraged to signal an error with condition type &assertion as in the R6RS, but this is not a requirement. The circumstances, if any, in which a domain error is required to signal an error will likewise be established in a future fascicle.

This fascicle contains entries. Each entry describes one language feature or a group of related features, where a feature is either a syntactic construct or a procedure. An entry begins with one or more header lines, each with a category.

If the category is syntax, the entry describes an expression type, and the template gives the syntax of the expression type.

If the category is auxiliary syntax, then the entry describes a syntax binding that occurs only as part of specific surrounding expressions. Any use as an independent syntactic construct or variable is an &syntax error.

Components of expressions are designated by syntactic variables. Syntactic variables are intended to denote segments of program text; for example, expression stands for any string of characters which is a syntactically valid expression. The notation thing1 indicates zero or more of thing.

If the category is procedure, then the entry describes a procedure, and the header line gives a template for a call to the procedure. Square brackets [] are used to denote optional arguments. Ellipses are used to denote the repetition of zero or more of a group of arguments.

The following variable names are used in the specifications of procedures to imply the type of the argument named by that variable:

alist

an association list (a list of pairs)

boolean

boolean

byte

exact integer, 0 ≤ byte ≤ 255

bytevector

bytevector

char

character

k

exact, non-negative integer

letter

alphabetic character

list

list

n

integer

obj

any object

pair

pair

proc

procedure

q

rational number

string

string

symbol

symbol

thunk

thunk

vector

vector

x or y

real number

z

complex number

nvector

An nvector

nelem

A valid element of an nvector

These conventions apply to the main component of the name of the argument. Some argument names contain subscripts to differentiate multiple arguments of the same type.

The names start and end are used as indexes into certain ordered objects (lists, vectors, bytevectors, and strings). Their use implies the following:

It is a domain error if an argument to any procedure does not match the expected type, whether the expected type is implied by the use of a variable name listed in this table, or named explicitly in the specification text.

Here is an example of a syntax declaration with auxiliary syntax:

Here is an example of a procedure declaration with optional arguments:

Here is an example of a procedure declaration with repeated argmuents:

In the description of expression syntax, an extended Backus-Naur form is used to document the possible forms that a syntactic variable can take. Ellipses are used to denote zero or more occurences of a syntactic variable. Spaces are not significant.

Throughout the document, there are examples that contain both definitions and expressions. To the right hand side of some expressions are what that expression would evaluate to, given the previous expressions and definitions in that example being evaluated. The evaluation will usually result in a Scheme value, but could result in an error being raised, a value printed to standard output, or an unspecified value being returned. Here is an example of evaluation:

(car '(1 . 2))1
(values 1 2)1 2
(car '())domain error

By convention, ? is the final character of the names of procedures that always return a boolean value. Such procedures are called predicates. Predicates are generally understood to be side-effect free, except that they may raise an exception when passed the wrong type of argument.

Similarly, ! is the final character of the names of procedures that store values into previously allocated locations TODO: storage model. Such procedures are called mutation procedures. The value returned by a mutation procedure is unspecified.

By convention, -> appears within the names of procedures that take an object of one type and return an analogous object of another type. For example, list->vector takes a list and returns a vector whose elements are the same as those of the list.

A command is a procedure that does not return useful values to its continuation.

A thunk is a procedure that does not accept arguments.

The key words must, must not, required, shall, shall not, should, should not, recommended, may, and optional in this document, although not capitalized in this report, are to be interpreted as described in RFC 2119. TODO: Bradner97

Comments of the form ... are editorial notes marking places requiring revision in the final report.

1: Numbers

This chapter describes Scheme’s model for numbers. It is important to distinguish between the mathematical numbers, the Scheme objects that attempt to model them, the machine representations used to implement the numbers, and notations used to write numbers. In this report, the term number refers to a mathematical number, and the term number object refers to a Scheme object representing a number. This report uses the types complex, real, rational, andinteger to refer to both mathematical numbers and number objects.[phm]: The term "number object" is confusing and pedantic. It should be removed and the terminology should be reverted back to the R5RS terminology. The fixnum and flonum refer to special subsets of the number objects, as determined by common machine representations, as explained below.

1.1: Numerical tower

Numbers may be arranged into a tower of subsets in which each level is a subset of the level above it:

For example, 5 is an integer. Therefore 5 is also a rational, a real, and a complex. The same is true of the number objects that model 5.

Number objects are organized as a corresponding tower of subtypes defined by the predicates number?, complex?, real?, rational?, and integer?; see section 1.6. Integer number objects are also called integer objects.

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.

1.2: Exactness

It is useful to distinguish between number objects that are known to correspond to a number exactly, and those number objects whose computation involved rounding or other errors. For example, index operations into data structures may need to know the index exactly, as may some operations on 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 numbers known only inexactly where exact numbers are required, Scheme explicitly distinguishes exact from inexact number objects. This distinction is orthogonal to the dimension of type.

A number object is exact if it is the value of an exact numerical literal or was derived from exact number objects using only exact operations. Exact number objects correspond to mathematical numbers in the obvious way.

Conversely, a number object is inexact if it is the value of an inexact numerical literal, or was derived from inexact number objects, or was derived using inexact operations. Thus inexactness is contagious.

Exact arithmetic is reliable in the following sense: If exact number objects are passed to any of the arithmetic procedures described in section TODO, and an exact number object is returned, then the result is mathematically correct. This is generally not true of computations involving inexact number objects because 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.

1.3: Fixnums and flonums

TODO

1.4: Implementation requirements

Implementations of Scheme must support number objects for the entire tower of subtypes given in section 1.1. Moreover, implementations must support exact integer objects and exact rational number objects of practically unlimited size and precision, and to implement certain procedures (listed in section TODO) so they always return exact results when given exact arguments. ( Practically unlimited means that the size and precision of these numbers should only be limited by the size of the available memory.)

Implementations may support only a limited range of inexact number objects of any type, subject to the requirements of this section. For example, an implementation may limit the range of the inexact real number objects (and therefore the range of inexact integer and rational number objects) to the dynamic range of the flonum format. Furthermore the gaps between the inexact integer objects and rationals are likely to be very large in such an implementation as the limits of this range are approached.Where does this leave mixed-exactness complex numbers? I read this as making them optional. Also how does "range" apply to complex numbers?

An implementation may use floating point and other approximate representation strategies for inexact numbers. This report recommends, but does not require, that the IEEE floating-point standards be followed by implementations that use floating-point representations, and that im- plementations using other representations should match or exceed the precision achievable using these floating-point standards TODO: cite IEEE 754.

In particular, implementations that use floating-point representations must follow these rules: A floating-point result must be represented with at least as much precision as is used to express any of the inexact arguments to that operation. Potentially inexact operations such as sqrt, when applied to exact arguments, should produce exact answers whenever possible (for example the square root of an exact 4 ought to be an exact 2). However, this is not required.Should the following two sentences be removed?If, on the other hand, an exact number object is operated upon so as to produce an inexact result (as by sqrt), nd if the result is represented in floating point, then the most precise floating-point format available must be used; but if the result is represented in some other way then the representation must have at least as much precision as the most precise floating-point format available.

It is the programmer’s responsibility to avoid using inexact number objects with magnitude or significand too large to be represented in the implementation.

Compatbility Note: The R6RS required exact integers and rationals of practically unlimited size and precision, and the whole numerical tower. The R7RS-Small did not. The R7RS-Large adopts the R6RS behavior.

1.5: IEEE arithmetic

TODO: Should we require IEEE 754?

1.6: Number predicates

These numerical type predicates can be applied to any kind of argument. They return #t if the object is a number object of the named type, and #f otherwise. In general, if a type predicate is true of a number object then all higher type predicates are also true of that number object. Consequently, if a type predicate is false of a number object, then all lower type predicates are also false of that number object.

1.6.1: number?

  • (number? obj) procedure
Semantics

Returns #t if the object is a number object, and #f otherwise.[phm]: Depending on the allowed extensions, this should have description similar to that in the R7RS-Small.

Examples

[phm]: These examples are not in previous reports.

(number? 0)#t
(number? 0.0)#t
(number? 1/2)#t
(number? 1+2i)#t
(number? "1")#f
(number? '(1))#f

1.6.2: complex?

  • (complex? obj) procedure
Semantics

Returns #t if the object is a complex number object, and #f otherwise.[phm]: Depending on allowed extensions, this should have discussion similar to the R7RS-Small.

Examples
(complex? 3+4i)#t
(complex? 3)#t

1.6.3: real?

  • (real? obj) procedure
Semantics

Returns #t if the object is a real number object, and #f otherwise. Equivalent to: [phm]: In a break from previous Reports, and more in-line with how SRFIs are written, this is written as a implementation.

(define (real? x)
  (and (complex? x)
       (zero? (imag-part x))))

Rationale: The R6RS defined a complex number object to be real if and only if it had an exact zero imaginary part. This differed from the R5RS definition. One of the reasons given for this change in the rationale of the R6RS is that real? could be used as a representational predicate separate from the usual representation of complex numbers. The R5RS definition was given the name real-valued?.

The R7RS-Small attemped to change the definition back to the R5RS definition, but the examples made it unclear if the R5RS or R6RS definition was required. Working Group 2 voted to restore the R5RS definition and give the R6RS definition the name strictly-real?.

Examples
(real? 3+4i)#f
(real? 3)#t
(real? -2.5+0i)#t
(real? -2.5+0.0i)#t
(real? -2.5-0.0i)#t
(real? #e1e10)#t
(real? +inf.0)#t
(real? +nan.0)#t

1.6.4: strictly-real?

  • (strictly-real? obj) procedure
Semantics

Returns #t iff the object is a real number object with an imaginary part that is exactly zero. Equivalent to

(define (strictly-real? obj)
  (and (real? obj)
       (exact? (imag-part obj))))

Rationale: The sign of the zero in the imaginary part of a complex number can change the behavior of the number when applied to trancendental functions, as the real number line is a common branch cut cite Kahan's paper. This predicate returns true when the number is exactly on the real line, and not possibly infinitesimally off of it.

Examples
(strictly-real? 3+4i)#f
(strictly-real? 3)#t
(strictly-real? -2.5+0i)#t
(strictly-real? -2.5+0.0i)#f
(strictly-real? -2.5-0.0i)#f
(strictly-real? #e1e10)#t
(strictly-real? +inf.0)#t
(strictly-real? +nan.0)#t

1.6.5: integer?

  • (integer? obj) procedure
Semantics

Returns #t if the object is an integer object, and #f otherwise. Equivalent to:

(define (integer? obj)
  (and (real? obj)
       (= obj (round obj))))

[phm]: This definition is taken from the R7RS-Small. Is the R6RS definition better?

Examples
(integer? 3+0i)#t
(integer? 3.0)#t
(integer? 8/4)#t
(integer? 3.1)#f
(integer? 3+1i)#f
(integer? 3+0.0i)#t
(integer? 3-0.0i)#t

1.6.6: strictly-integer?

  • (strictly-integer? obj) procedure
Semantics

Returns #t iff the object is an integer object with an imaginary part that is exactly zero. Equivalent to

(define (strictly-integer? obj)
  (and (integer? obj)
       (exact? (imag-part obj))))
Examples
(strictly-integer? 3+0i)#t
(strictly-integer? 3.0)#t
(strictly-integer? 8/4)#t
(strictly-integer? 3.1)#f
(strictly-integer? 3+1i)#f
(strictly-integer? 3+0.0i)#f
(strictly-integer? 3-0.0i)#f

1.7: Complex number procedures

1.7.1: conjugate

  • (conjugate z) procedure
Semantics

Returns the complex conjugate of z.

Examples
(conjugate 1+2i)1-2i
(conjugate 1+inf.0i)1-inf.0i
(conjugate 1+0.0i)1-0.0i
(conjugate 1)1

2: Booleans

[phm]: R7RS with minor modifications

The standard boolean objects for true and false are written as #t and #f. Alternatively, when the R6RS lexical mode is not enabled, 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 true or 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

2.1: Boolean procedures

2.1.1: not

  • (not obj) procedure
Semantics

Returns #t if obj is false, and #f otherwise.

Examples
(not #t)#f
(not 3)#f
(not (list 3))#f
(not #f)#t
(not '())#f
(not (list))#f
(not 'nil)#f

2.1.2: boolean?

  • (boolean? obj) procedure
Semantics

Returns #t if obj is either #t or #f and returns #f otherwise.

Examples
(boolean? #f)#t
(boolean? 0)#f
(boolean? ’())#f

2.1.3: boolean=?

  • (boolean? boolean1 boolean2 boolean3) procedure
Semantics

Returns #t if all the arguments are either all #t or all #f.

3: 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 list or a pair whose cdr is a list. More precisely, the set of lists is defined as the smallest set X such that

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 list is 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 (datum1 . datum2)where datum1 is the representation of the value of the car field and datum2 is the value of the cdr field. For example (4 . 5) is a pair whose car is 4 and whose cdr is 5.

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 list is represented by (). For example,

(a b c d e)

and

(a . (b . (c . (d . (e . ())))))

are equivalent notations for a list of symbols. The general rule is that, if a dot is followed by an open parenthesis, the dot, open parenthesis, and matching closing parenthesis can be omitted in the external representation.

Note that (4 . 5)is the external representation of a pair, not an expression that evaluates to a pair. Similarly, the sequence of characters (+ 2 6) is notan external representation of the integer 8, even though it is an expression (in terms of the procedures described here) evaluating to the integer 8; rather, it is a syntactic datum representing a three-element list, the elements of which are the symbol + and the integers 2 and 6.[phm]: Derived from the R6RS description.

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)))

The length of an improper list is the number of pairs before the non-list cdr. This number may be infinity. The elements of an improper list are the cars of each pair in the list.

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 TODO). Among other things, this permits the use of the read procedure to parse Scheme programs. See section TODO.

3.1: Pair procedures

3.1.1: pair?

  • (pair? obj) procedure
Semantics

Returns #t if obj is a pair, and otherwise returns #f.

Examples
(pair? '(a . b))#t
(pair? (cons 'a 'b))#t
(pair? '(a b c))#t
(pair? '())#f
(pair? '#(a b))#f

3.1.2: cons

  • (cons obj1 obj2) procedure
Semantics

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.

Examples
(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)

3.1.3: car and cdr

  • (car pair) procedure
  • (cdr pair) procedure
Semantics

Returns the car or cdr field of the pair, respectively.[phm]: merged descriptions

Examples
(car '(a b c))a
(car '((a) b c d))(a)
(car '(1 . 2))1
(car '())domain error

3.1.4: set-car! and set-cdr!

  • (set-car! pair obj) procedure
  • (set-cdr! pair obj) procedure
Semantics

Store obj in the car or cdr field of pair, respectively.[phm]: merged descriptions

Examples
(define f (list 'not-a-constant-list))
(set-car! f 3)unspecified
f(3)
(set-cdr! f 4)unspecified
f(3 . 4)
(set-car! '(constant-list) 3)domain error

3.1.5: Compositions

  • (ccompositionr pair) procedure
Restrictions

TODO

Semantics

These procedures are compositions of car and cdr. The composition is any string of a and d from two to four (inclusive) characters. For example, caddr could be defined as

(define (caddr pair) (car (cdr (cdr pair))))

Arbitrary compositions up to four deep are provided. There are twenty-eight of these procedures in all.

3.2: Basic list procedures

3.2.1: null?

  • (null? obj) procedure
Semantics

Returns #t if obj is the empty list, and otherwise returns #f.

3.2.2: list?

  • (list? obj) procedure
Semantics

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.

Examples
(list? '(a b c))#t
(list? '())#t
(list? '(a . b))#f
(list? '#1=(a . #1#))#f

3.2.3: list

  • (list obj) procedure
Semantics

Returns a newly allocated list of its arguments.

Examples
(list 'a (+ 3 4) 'c)(a 7 c)
(list)()

3.2.4: make-list

  • (make-list k [fill]) procedure
Semantics

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.

Examples
(make-list 2 3)(3 3)

3.2.5: list-tail

  • (list-tail list k) procedure
Restrictions

The list can be improper, but it must start with a chain of at least k pairs. Otherwise, it is a domain error.[phm]: Modified to allow circular and dotted lists.

Semantics

Returns the sublist of list obtained by omitting the first k elements.[phm]: Add share-structure statement?

Examples
(list-tail '(a b c d) 2)(c d)
Sample Implementation
(define (list-tail list k)
  (if (zero? k)
      list
      (list-tail (cdr list) (- k 1))))

3.2.6: list-ref

  • (list-ref list k) procedure
Restrictions

The list argument can be improper, but it must start with a chain of more than k elements. Otherwise, it is a domain error.[phm]: Modified to allow circular and dotted lists.

Semantics

Returns the kth element of list.

Examples
(list-ref '(a b c d) 2)c
(list-ref '(a b c d) (exact (round 1.8)))c
Sample Implementation
(define (list-ref list k)
  (car (list-tail list k)))

3.2.7: list-set!

  • (list-set! list k obj) procedure
Restrictions

The list argument can be improper, but it must start with a chain of more than k elements. Otherwise, it is a domain error.[phm]: Modified to allow circular and dotted lists.

Semantics

Stores obj in element k of list.

Examples
(let ((ls (list 'one 'two 'five!)))
  (list-set! ls 2 'three)
  ls)(one two three)
(list-set! '(0 1 2) 1 "oops")domain error
Sample Implementation
(define (list-set! list obj k)
  (set-car! (list-tail list k) obj))

3.3: Bulk list procedures

3.3.1: length

  • (length list) procedure
Semantics

Returns a newly allocated list of its arguments.

Examples
(list 'a (+ 3 4) 'c)(a 7 c)
(list)()

3.3.2: append

  • (append list [obj]) procedure
Semantics

Returns a (possibly improper) 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.

Examples
(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

3.3.3: reverse

  • (reverse list) procedure
Semantics

Returns a newly allocated list consisting of the elements of list in reverse order.

Examples
(reverse '(a b c))(c b a)
(reverse '(a (b c) d (e (f)))) ((e (f)) d (b c) a)

3.3.4: list-copy

  • (list-copy obj [start [end]]) procedure
Restrictions

If neither start or end are given, the it is a domain error if obj is circular.

Semantics

Copies a list or improper list.

If neither start nor end is supplied, then this procedure returns a newly allocated copy of the sequence of pairs at the start of obj. 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.

If start but not end is supplied, this procedure is equivalent to(list-copy (list-tail im-list start)).

If both start and end are supplied, then the startth pair to the endth pair are copied, and the list is terminated with an empty list.

In any case, only the pairs themselves are copied; the cars of the pairs in the result are the same (in the sense of eqv?) as the cars of the corresponding pairs that were copied from obj.

Compatability Note: This procedure originally appeared in SRFI 1 and was added to R7RS Small. The R7RS Large extended the procedure to take start and end arguments.

3.4: Higher order list procedures

3.4.1: map

  • (map proc list1 list2) procedure
Restrictions

It is a domain error if proc does not accept as many arguments as there are lists and return a single value.

The lists can be circular, but if all of them are circular, it is undefined behavior.

If proc mutates any of the lists, it is undefined behavior.

Semantics

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 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.

The procedure proc is always called in the same dynamic environment as the call to map.

Examples
(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)))unspecified
either (1 2) or (2 1)

3.4.2: for-each

  • (for-each proc list1 list2) procedure
Restrictions

It is a domain error if proc does not accept as many arguments as there are lists.

The lists can be circular, but if all of them are circular, it is undefined behavior.

If proc mutates any of the lists, it is undefined behavior.

Semantics

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.[phm]: Because for-each cannot returned unspecified values, an implementation cannot tail-call proc on the last element(s).

The procedure proc is always called in the same dynamic environment as the call to for-each.

Examples
(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)

3.5: List query procedures

3.5.1: memq, memv, and member

[phm]: This is PROPOSED, NOT final.
  • (memq obj list) procedure
  • (memv obj list) procedure
  • (member obj list [compare]) procedure
Restrictions

The compare, if present, must be a procedure that accepts two arguments and returns one value.

Semantics

These procedures return the first sublist sl of list such that (C obj (car sl)) returns true. The sublists of list are the non-empty lists returned by (list-tail list k) for k less than the length of list. If the condition is never satisfied for any sublist, then #f (not the empty list) is returned.

For memq, eq? is used. For memv, eqv? is used. For member, compare is used if given, otherwise equal? is used.

Compatability Note: The optional argument to member was in SRFI 1 and included in the R7RS-Small. The argument order to compare was unspecified in R7RS-Small, but was in SRFI 1. The R7RS-Large adopts the SRFI 1 behavior.

Examples
(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)
(member 5 '(1 2 3 4 5 6 7 8) <)(6 7 8)

3.5.2: assq, assv, and assoc

[phm]: This is PROPOSED, NOT final.
  • (assq obj list) procedure
  • (assv obj list) procedure
  • (assoc obj list [compare]) procedure
Restrictions

The compare, if present, must be a procedure that accepts two arguments and returns one value. The alist must be a list of pairs.

Semantics

These procedures return the first pair p of alist such that (C obj (car p)) returns true.. If the condition is never satisfied for any pair, then #f (not the empty list) is returned.

For assq, eq? is used. For assv, eqv? is used. For assoc, compare is used if given, otherwise equal? is used.

Compatability Note: The optional argument to assoc was in SRFI 1 and included in the R7RS-Small. The argument order to compare was unspecified in R7RS-Small, but was in SRFI 1. The R7RS-Large adopts the SRFI 1 behavior.

Examples
(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)
(assoc 3 '((1 a) (2 b) (3 c) (4 d) (5 e)) <)(4 d)

4: 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 TODO.

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.

4.1: Symbol procedures

4.1.1: symbol?

  • (symbol? obj) procedure
Semantics

Returns #t if obj is a symbol, and #f otherwise.

Examples
(symbol? 'foo)#t
(symbol? (car '(a b)))#t
(symbol? "bar")#f
(symbol? 'nil)#t
(symbol? '())#f
(symbol? #f)#f

4.1.2: symbol=?

  • (symbol=? symbol1 symbol2 symbol3) procedure
Semantics

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.

4.1.3: symbol->string

  • (symbol->string symbol) procedure
Semantics

Returns the name of symbol as a string, but without adding escapes.[phm]: Is that "escapes" part necessary?

The returned string may either be immutable or freshly allocated.[phm]: Merge with some other section on immutable values?

Examples
(symbol->string 'flying-fish)"flying-fish"
(symbol->string 'Martin)"Martin"
(symbol->string (string->symbol "Malvina"))Malvina

4.1.4: string->symbol

  • (string->symbol string) procedure
Semantics

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.[phm]: Is the escaping text redundant?

Examples
(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

5: Characters

[phm]: From R6RS

Characters are objects that represent Unicode scalar values.

Note: Unicode defines a standard mapping between sequences of Unicode scalar values (integers in the range 0 to #x10FFFF, excluding the range #xD800 to #xDFFF) in the latest version of the standard and human-readable characters.[phm]: That previous sentence should be reworded. More precisely, Unicode distinguishes between glyphs, which are printed for humans to read, and characters, which are abstract entities that map to glyphs (sometimes in a way that’s sensitive to surrounding characters). Furthermore, different sequences of scalar values sometimes correspond to the same character. The relationships among scalar, characters, and glyphs are subtle and complex.

Despite this complexity, most things that a literate human would call acharacter can be represented by a single Unicode scalar value (although several sequences of Unicode scalar values may represent that same character). For example, Roman letters, Cyrillic letters, Hebrew consonants, and most Chinese characters fall into this category.

Unicode scalar values exclude the range #xD800 to #xDFFF, which are part of the range of Unicode code points. However, the Unicode code points in this range, the so-called surrogates, are an artifact of the UTF-16 encoding, and can only appear in specific Unicode encodings, and even then only in pairs that encode scalar values. Consequently, all characters represent code points, but the surrogate code points do not have representations as characters.

Compatibility Note: The R6RS required Scheme programs to be written in sequences of Unicode scalar values. The R7RS-Small allowed for non-Unicode characters as long as #x0 and #x7F were the ASCII characters, that char->integer and integer->char treated non-Unicode characters as having integer values greater than Unicode characters, and that certain procedures were defined on Unicode scalar values according to certain properties and annexes of the Unicode standard. The R7RS-Large adopts the R6RS behavior.

5.1: Syntax

The grammar of character constants is:

character
::= #\any character
::= #\character name
::= #\xhex scalar value
character name
::= alarm
::= backspace
::= delete
::= escape
::= newline
::= null
::= return
::= space
::= tab
R6RS character name
::= alarm
::= backspace
::= delete
::= esc
::= linefeed
::= newline
::= nul
::= page
::= return
::= space
::= tab
::= vtab

The R6RS character names are used instead of the character names when the parser is set to R6RS mode.

Case is significant in #\character, and in #\character name, but not in #\xhex scalar value. A character must be followed by a delimiter or by the end of the input. This rule resolves various ambiguous cases involving named characters, requiring, for example, the sequence of characters #\space to be interpreted as the space character rather than as the character #s followed by the identifier pace.

Characters written in the #\ notation are self-evaluating. That is, they do not have to be quoted in programs.[phm]: Extension paragraph?

Compatability Note: The R6RS introduced more control characters for the ASCII control characters that commonly had escape sequences in other programming languages. The R7RS-Small adopted a different set of names and escape sequences, intended to be more mnemonic, and to remove rarely used codes such as vertical tab and form feed. The R7RS-Large adopts the R7RS-Small convention.

The meaning of each escape sequence (R6RS-specific escape sequence in parentheses) is:

#\alarm
U+0007
#\backspace
U+0008
#\delete
U+007F
#\escape (#\esc)
U+001B
#\newline (#\linefeed)
U+000A (the linefeed character)
#\null (#\nul)
U+0000 (the NUL character)
(#\page)
U+000C (the form feed character)
#\return
U+000D (the return character)
#\space
U+0020 (the space character)
#\tab
U+0009 (the horiziontal tab character)
(#\vtab)
U+000B (the vertical tab character)

A character written as #\hex scalar value is the character associated with that Unicode scalar value.

5.1.1: Examples

[phm]: TODO: how to mark this up?

5.2: Character procedures

5.2.1: char?

  • (char? obj) procedure
[phm]: From R6RS/R7RS
Semantics

Returns #t if obj is a character, or #f otherwise.

5.2.2: char->integer

  • (char->integer char) procedure
[phm]: From R6RS
Semantics

Returns the unicode scalar value of char as an exact integer.

Examples
[phm]: New example
(char->integer #\x10FFFF)#x10FFFF

5.2.3: integer->char

  • (integer->char sv) procedure
[phm]: From R6RS
Restrictions

The sv must be an exact integer Unicode scalar value, which is equivalent to the following evaluating to true:

(or (<= 0 sv #xD7FF) (<= #xE000 sv #x10FFFF))
Semantics

Returns the character associated with the scalar value.

Examples
(integer->char 32)#\space
(char->integer (integer->char 5000))5000
(integer->char #xD800)&assertion exception

5.2.4: Character comparisions

  • (char=? char1 char2 charn) procedure
  • (char<? char1 char2 charn) procedure
  • (char>? char1 char2 charn) procedure
  • (char<=? char1 char2 charn) procedure
  • (char>=? char1 char2 charn) procedure
[phm]: From R6RS, second paragraph is from R7RS
Semantics

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.

Examples
(char<? #\z #\ß)#t
(char<? #\z #\Z)#f

5.3: Unicode

This library provides access to locale-independent Unicode transformations for characters.

These procedures are consistent with Unicode’s locale- independent mappings from scalar values to scalar values for upcase, downcase, titlecase, and case-folding operations. These mappings can be extracted from UnicodeData.txt and CaseFolding.txtfrom the Unicode Consortium, ignoring language-dependent mappings in the latter.

These character-based procedures are an incomplete approximation to case conversion, even ignoring the user’s locale. In general, case mappings require the context of a string, both in arguments and in result. The string-upcase, string-downcase, and string-foldcase procedures add section perform more general case conversion.

Compatability Note: The definitions of these procedures comes from the R7RS-Small, modified for current Unicode support. Titlecasing procedures are not included.

5.3.1: char-upcase

  • (char-upcase string) procedure
Semantics

Given an argument that is the lowercase part of a Unicode casing pair, returns the uppercase member of the pair. Note that language-sensitive casing pairs are not used. If the argument is not the lowercase member of such a pair, it is returned.

Examples
(char-upcase #\i)#\I
(char-upcase #\ß)#\ß
(char-upcase #\Σ)#\Σ
(char-upcase #\ς)#\Σ

5.3.2: char-downcase

  • (char-downcase string) procedure
Semantics

Given an argument that is the uppercase part of a Unicode casing pair, returns the lowercase member of the pair. Note that language-sensitive casing pairs are not used. If the argument is not the uppercase member of such a pair, it is returned.

Note: Note that many Unicode lowercase characters do not have uppercase equivalents.

Examples
(char-downcase #\i)#\i
(char-downcase #\ß)#\ß
(char-downcase #\Σ)#\σ
(char-downcase #\ς)#\ς

5.3.3: char-foldcase

  • (char-foldcase string) procedure
Semantics

Applies the Unicode simple case-folding algorithm to its argument and returns the result. Note that language-sensitive folding is not used.

Note: Note that many Unicode lowercase characters do not have uppercase equivalents.

Examples
(char-downcase #\i)#\i
(char-downcase #\ß)#\ß
(char-downcase #\Σ)#\σ
(char-downcase #\ς)#\ς

5.3.4: Case-insensitive comparisons

  • (char-ci=? char1 char2 char3) procedure
  • (char-ci<? char1 char2 char3) procedure
  • (char-ci>? char1 char2 char3) procedure
  • (char-ci<=? char1 char2 char3) procedure
  • (char-ci>=? char1 char2 char3) procedure
Semantics

These procedures are similar to char=?, etc., but operate on the case-folded versions of the characters.

Examples
(char-ci<? #\z #\Z)#f
(char-ci=? #\z #\Z)#t
(char-ci=? #\ς #\σ)#t

5.3.5: char-alphabetic?

  • (char-alphabetic? char) procedure
Semantics

Returns #t if it has the Unicode Alphabetic property. Otherwise returns #f.

Examples
char-alphabetic? #\a#t

5.3.6: char-numeric?

  • (char-numeric? char) procedure
Semantics

Returns #t if it has the Unicode Numeric_Type property equal to Decimal. Otherwise returns #f.

Examples
char-alphabetic? #\1#t

5.3.7: char-whitespace?

  • (char-whitespace? char) procedure
Semantics

Returns #t if it has the Unicode White_Space property. Otherwise returns #f.

Examples
char-whitespace? #\space#t
char-whitespace? #\x00A0#t

5.3.8: char-upper-case?

  • (char-upper-case? char) procedure
Semantics

Returns #t if it has the Unicode Uppercase property. Otherwise returns #f.

Examples
char-uppercase? #\Σ#t

5.3.9: char-lower-case?

  • (char-lower-case? char) procedure
Semantics

Returns #t if it has the Unicode Lowercase property. Otherwise returns #f.

Examples
char-lowercase? #\σ#t
char-lowercase? #\x00AA#t

6: Strings

Strings are sequences of characters.

The length of a string is the number of characters that it contains. This number is fixed when the string is created. The valid indicies 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.

Compatability Note: The R7RS-Small allowed implementations to forbid certain characters in strings, as long as every ASCII character that was not U+0000 (ASCII NUL) was allowed. The R6RS allows all characters in a string. The R7RS-Large adopts the R6RS behavior.

6.1: String Syntax

String literals are written as sequences of characters enclosed within quotation marks (", U+0022). Within a string literal, various escape sequences represent characters other than themselves. Escape sequences always start with a backslash (\, U+005C):

These escape sequences are case-sensitive, except that the alphabetic digits of a hex scalar value can be uppercase or lowercase.

Compatability Note: The R6RS made it a &lexical violation to use any other character than the ones specified as an escape character. The R7RS-Small made it unspecified what happens when a character not listed above was used in an escape sequence.[phm]: TODO: specify that extension is OK, except for code using #!r7rs or similar. Also specify behavior when using #!r6rs.

Examples

""""
a string with zero length
"abc""abc"
a string of three characters, U+0061, U+0062, and U+0063
"A"a string with one character, U+0041
"\x41;bc""Abc"
a string of three characters, U+0041, U+0062, and U+0063
"\x41; bc""A bc"
a string of four characters, U+0041, U+0020, U+0062, and U+0063
"\x41bc;""\x41bc;"
a string of one character, U+41BC
"\x41Bc;""\x41bc;"
a string of one character, U+41BC
"\x41"&lexical exception
"\x;"&lexical exception
"\x00000041;""A"
a string with one character, U+0041
"\x0010FFFF;""\x10ffff;"
a string with one character, U+10FFFF
"\x00110000;"&lexical exception
out of range
"\xD800;"&lexical exception
in excluded range
"A
bc""a\nbc"
if no space appears after A, a string of four characters, U+0061, U+000A, U+0062, and U+0063
"ΧΑΟΣ""ΧΑΟΣ"
a string of four characters, U+03A7, U+0391, U+039F, and U+03A3
"\n"a string of one character, U+000A
"Here's text \
  containing just one line""Here's text containing just one line"

6.2: Raw String Syntax

Raw strings are an alternative syntax for string literals that do not interpret escape sequences inside of them.

The string S is written as a raw string using the notation #"delimiter"string data"delimiter", where string data is the characters of S; with the restriction that S does not contain "delimiter" as a substring, and does not contain "delimiter as a suffix. Since the delimiter can be freely chosen, any string can be represented as a raw string with a suitable choice of delimiter. All characters in S are repesented literally in the string.

Examples

#""""""
#""\begin{document}"""\\begin{document}"
#"--")")")"-""--"")\")\")-\")"
#""a"""a"
#""\"""\\"
#"-"""-""\""
#"-" " "-"" \" "
#"-"#""a"""-""#\"\"a\"\""
#"-"ends with \""-""ends with \\\""
#""multiline
string"""multiline\nstring"
#""
    no whitespace stripping"""\n    no whitespace stripping"
#""{"first_name" : "John",
"last_name" : "Doe"}"""{\"first_name\" : \"John\",\n\"last_name\" : \"Doe\"}"
#""\(?(\d{3})\D{0,3}(\d{3})\D{0,3}(\d{4})"""\\(?(\\d{3})\\D{0,3}(\\d{3})\\D{0,3}(\\d{4})"

6.3: Fundamental string procedures

[phm]: String mutation deprecated?

6.3.1: string?

  • (string? obj) procedure
Semantics

Returns #t if obj is a string, and #f otherwise.

6.3.2: make-string

  • (make-string k [char]) procedure
Semantics

[phm]: Require fixnums here and everywhere else.

Returns a newly allocated string of length k. If char is given, then all elements of the string are initialized to char, otherwise the contents of the string are unspecified.

Examples

[phm]: These are new examples

(make-string 5 #\a)"aaaaa"
(equal? "a" (make-string 1))unspecified

6.3.3: string

  • (string char) procedure
Semantics

Returns a newly allocated string composed of the arguments.

Examples

[phm]: These are new examples

(string)""
(string #\a #\b #\c)"abc"

6.3.4: string-length

  • (string-length string) procedure

[phm]: R6RS without integer object vocabulary

Semantics

Returns the number of characters in the given string as an exact integer.

Examples

[phm]: These are new examples

(string-length "")0
(string-length "abc")3

6.3.5: string-ref

  • (string-ref string k) procedure

[phm]: R7RS

Restrictions

The k must be a valid index of the string.

Semantics

Returns character k of string using zero-origin indexing.

Compatability Note: Some implementations may use variable-length string encodings, like UTF-8, for all of their strings. Hence, this procedure may run in O(n) time, where n is the length of the string. Implementers should make this procedure run in constant time.

Examples

[phm]: These are new examples

(string-ref "ab" 0)#\a
(string-ref "ab" 1)#\b
(string-ref "ab" 2)&assertion exception

6.4: Bulk string procedures

6.4.1: string=?

  • (string=? string1 string2 stringn) procedure

[phm]: R7RS

Semantics

Returns #t if the strings are the same length and contain the same characters in the same positions. Otherwise, the string=? procedure returns #f.

Examples

[phm]: These are R6RS and new examples

(string=? "Straße" "Strasse")#f
(string=? "abc" "aBc")#f

6.4.2: String ordering predicates

[phm]: R6RS

  • (string<? string1 string2 stringn) procedure
  • (string>? string1 string2 stringn) procedure
  • (string<=? string1 string2 stringn) procedure
  • (string>=? string1 string2 stringn) procedure
Semantics

These procedures are the lexicographic extensions to strings of the corresponding orderings on characters. For example, string<? is the lexicographic ordering on strings induced by the ordering char<? on characters. If two strings differ in length but are the same up to the length of the shorter string, the shorter string is considered to be lexicographically less than the longer string.

Compatability Note: The R7RS-Large uses the behavior of the R5RS and the R6RS for these procedures. The R7RS-Small left it implementation defined what specific ordering was used for strings.

Examples
(string<? "z" "ß")#t
(string<? "z" "zz")#t
(string<? "z" "Z")#f

6.4.3: string-copy and substring

[phm]: R7RS

  • (string-copy string [start [end]]) procedure
  • (substring string start end) procedure
Semantics

Returns a newly allocated copy of part of string from start to end.

The procedure substring is an alias for string-copy except that all arguments are requied.

Compatability Note: The procedure substring was introduced in the R6RS. The R7RS-Small extended the string-copy procedure to take optional arguments.

Examples

[phm]: SRFI-13 examples

(string-copy "Beta substitution")"Beta substitution"
(let* ((s1 (string-copy "abc"))
       (s2 (string-copy s1)))
  (string-set! s1 0 #\A)
  (values s1 s2))"Abc" "abc"
(string-copy "Beta substitution" 1 10)"eta subst"
(string-copy "Beta substitution" 5)"substitution"

6.4.4: string-append

  • (string-append string) procedure

[phm]: R7RS with new examples

Semantics

Returns a newly allocated string whose characters are the concatenation of the characters in the given strings.

Examples
(string-append "abc" "def")"abcdef"
(string-append)""

6.5: String conversion procedures

6.5.1: string->list

  • (string->list string [start [end]]) procedure

[phm]: R7RS with new examples

Semantics

Returns a newly allocated list of the characters of string between start and end in order.

This procedure and list->string are inverses so far as equal? is concerned.

Examples
(string->list "abcdef")(#\a #\b #\c #\d #\e #\f)
(string->list "abcdef" 2)(#\c #\d #\e #\f)
(string->list "abcdef" 2 5)(#\c #\d #\e)
(string->list "abcdef" 0 0)()
(list->string (string->list "abcdef"))"abcdef"

6.5.2: list->string

  • (list->string list [start [end]]) procedure

[phm]: R7RS with new examples

Restrictions

The list must be a list of characters.

Semantics

Returns a newly allocated string formed from the characters in list between start and end in order.

This procedure and string->list are inverses so far as equal? is concerned.

Compatability Note: The R7RS Large added start and end arguments to this procedure.

Examples
(list->string '(#\s #\c #\m))"scm"
(list->string '())""
(string->list (list->string '(#\s #\c #\m)))(#\s #\c #\m)

6.6: Higher order string procedures

6.6.1: string-for-each

  • (string-for-each proc string1 string2) procedure

[phm]: R7RS using R6RS wording

Restrictions

The proc must accept as many arguments as there are strings, otherwise it is a domain error. It is undefined behavior for proc to mutate any of the strings.

Semantics

Applies proc element-wise to the characters of the strings for its side effects, in order from the first characters to the last. The proc always called in the same dynamic environment as the call to string-for-each. 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.

This procedure returns an unspecified value.

Examples
(let ((v '()))
  (string-for-each
   (lambda (c) (set! v (cons (char->integer c) v)))
   "abcde")
  v)(101 100 99 98 97)

6.6.2: string-map

  • (string-map proc string1 string2) procedure

[phm]: R7RS with reduced examples

Restrictions

The proc must accept as many characters as there are strings and return a single character.

Semantics

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 proc is always called in the same dynamic environment as the call to string-map. 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.

Examples
(string-map
 (lambda (c)
   (integer->char (+ 1 (char->integer c))))
 "HAL")"IBM"

6.7: Unicode procedures

This library provides access to locale-independent Unicode transformations for strings.

6.7.1: Case conversion

  • (string-upcase string) procedure
  • (string-downcase string) procedure
  • (string-titlecase string) procedure
Semantics

These procedures take a string argument and return a string result. They are defined in terms of Unicode’s locale-independent case mappings from Unicode scalar-value sequences to scalar-value sequences. In particular, the length of the result string can be different from the length of the input string. When the specified result is equal in the sense of string=? to the argument, these procedures may return the argument instead of a newly allocated string.

The procedures convert the string to uppercase, lowercase, and case-folded versions respectively. Case folding is done using the full case-folding mapping, but without the special mappings for Turkic languages.

Note: The case mappings needed for implementing these procedures can be extracted from UnicodeData.txt, SpecialCasing.txt, WordBreakProperty.txt, (the MidLetter property partly defines case-ignorable characters), and CaseFolding.txt from the Unicode Consortium.

Since these procedures are locale-independent, they may not be appropriate for some locales.

Note: Word breaking, as needed for the correct casing of Σ, is specified in Unicode Standard Annex #29.cite unicode

Compatability Note: These procedures have the semantics of the ones in the R6RS. The titlecasing procedures are not included.

Examples
(string-upcase "Hi")"HI"
(string-downcase "Hi")"hi"
(string-foldcase "Hi")"hi"
(string-upcase "Straße")"STRASSE"
(string-downcase "Straße")"straße"
(string-foldcase "Straße")"strasse"
(string-downcase "STRASSE")"strasse"
(string-downcase "Σ")"σ"
(string-upcase "ΧΑΟΣ")"ΧΑΟΣ"
(string-downcase "ΧΑΟΣ")"χαoς"
(string-downcase "ΧΑΟΣΣ")"χαoσς"
(string-downcase "ΧΑΟΣ Σ")"χαoς σ"
(string-foldcase "ΧΑΟΣΣ")"χαoσσ"
(string-upcase "χαoς")"ΧΑΟΣ"
(string-upcase "χαoσ")"ΧΑΟΣ"

6.7.2: Case-insensitive comparisons

  • (string-ci=? string1 string2 string3) procedure
  • (string-ci<? string1 string2 string3) procedure
  • (string-ci>? string1 string2 string3) procedure
  • (string-ci<=? string1 string2 string3) procedure
  • (string-ci>=? string1 string2 string3) procedure
Semantics

These procedures are similar to string=?, etc., but operate on the case-folded versions of the strings.

Examples
(string-ci<? "z" "Z")#f
(string-ci=? "z" "Z")#t
(string-ci=? "Straße" "Strasse")#t
(string-ci=? "Straße" "STRASSE")#t
(string-ci=? "XAOΣ" "χαoσ")#t

6.8: Mutating string procedures

[phm]: Say this explicitly?String mutation is deprecated.

Implementations are allowed to store strings in variable length encodings such as UTF-8. A user-visible Unicode character may not be a single Unicode codepoint.

6.8.1: string-set!

  • (string-set! string k char) procedure

[phm]: R7RS with modified examples

Restrictions

The k must be a valid index of the string.

Semantics

Stores char in element k of string. There is no requirement for this procedure to execute in constant time.

Examples
(define (f) (make-string 3 #*))
(define s (f))
(string-set! s 0 #\?)unspecified
s"?**"

[phm]: Enforce immutablity of string literals?

6.8.2: string-copy!

  • (string-copy! to at from [start [end]]) procedure

[phm]: R7RS with new examples

Restrictions

The following must be satisfied:

(and (<= 0 at (string-length to))
     (>= (- (string-length to) at) (- end start)))
Semantics

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.

Examples
(define a 12345)
(define b (string-copy "abcde"))
(string-copy! b 1 a 0 2)
b"a12de"

6.8.3: string-fill!

  • (string-fill! string fill [start [end]]) procedure

[phm]: R7RS with new examples

Restrictions

The fill must be a character.

Semantics

Stores fill in the elements of string between start and end.

Examples
(define s (string-copy "hello world"))
(string-fill! s #c 6)
s"hello ccccc"

7: 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 indexes of 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 #(datum). 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.

7.1: Fundamental vector procedures

7.1.1: vector?

  • (vector? obj) procedure
Semantics

Returns #t if obj is a vector; otherwise returns #f.

Examples
(vector? '#())#t
(vector? '(vector 1 2 3))#f
(vector? '#(1 2 3))#t

7.1.2: make-vector

  • (make-vector k [fill]) procedure
Semantics

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.

Examples
(make-vector 3 0)#(0 0 0)

7.1.3: vector

  • (vector obj) procedure
Semantics

Returns a newly allocated vector whose elements are the given arguments. It is analogous to list.

Examples
(vector 'a 'b 'c)#(a b c)

7.1.4: vector-length

  • (vector-length vector) procedure
Semantics

Returns the number of elements in vector as an exact integer.

Examples
(vector-length '#())0
(vector-length '#(a b c))3

7.1.5: vector-ref

  • (vector-ref vector k) procedure
Restrictions

It is a domain error if k is not a valid index of vector.

Semantics

Returns the contents of the element k of the vector.

Examples
(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

7.1.6: vector-set!

  • (vector-set! vector k obj) procedure
Restrictions

It is a domain error if kis not a valid index of vector.

Semantics

Stores obj in element k of vector.

Examples
(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")domain error

7.2: Vector conversion procedures

7.2.1: vector->list

  • (vector->list vector [start [end]]) procedure
Semantics

Returns a newly allocated list of objects contained of vector between start and end. Order is preserved.

Examples
(vector->list '#(dah dah didah))(dah dah didah)
(vector->list '#(dah dah didah) 1 2)(dah)

7.2.2: list->vector

  • (list->vector list [start [end]]) procedure
Semantics

Returns a newly created vector initialized to the elements of list between start and end. Order is preserved.

Compatability Note: The R7RS Large added start and end arguments to this procedure.

Examples
(list->vector '(dididit dah))#(dididit dah)

7.2.3: vector->string

  • (vector->string vector [start [end]]) procedure
Restrictions

It is a domain error if any element of vector between start and end is not a character.

Semantics

Returns a newly allocated string of the characters of vector between start and end. Order is preserved.

Examples
(vector->string
 '#(#\1 #\2 #\3)"123"

7.2.4: string->vector

  • (string->vector vector [start [end]]) procedure
Semantics

Returns a newly created vector initialized to the characters of string between start and end. Order is preserved.

Examples
(string->vector "ABC")#(#\A #\B #\C)

7.3: Bulk vector procedures

7.3.1: vector-copy

  • (vector-copy vector [start [end]]) procedure
Semantics

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.

Examples
(define a #(1 8 2 8)) ; a may be immutable
(define b (vector-copy a)) ; b is mutable
(vector-set! b 0 3)unspecified
(define c (vector-copy b 1 3))
c#(8 2)

7.3.2: vector-copy!

  • (vector-copy! to at from [start [end]]) procedure
Restrictions

It is a domain error if at is less than zero or greater than the length of to. It is also a domain error if (- (vector-length to) at) is less than (- end start).

Semantics

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.

Examples
(define a (vector 1 2 3 4 5))
(define b (vector 10 20 30 40 50))
(vector-copy! b 1 a 0 2)unspecified
b#(10 1 2 40 50)

7.3.3: vector-append

  • (vector-append vector) procedure
Semantics

Returns a newly allocated vector whose elements are the concatenation of the elements of the given vectors.

Examples
(vector-append #(a b c) #(d e f))#(a b c d e f)

7.3.4: vector-fill!

  • (vector-fill! vector fill [start [end]]) procedure
Semantics

Stores fill in the elements of vector between start and end.

Examples
(define a (vector 1 2 3 4 5))
(vector-fill! a 'smash 2 4)unspecified
a#(1 2 smash smash 5)

7.4: Higher order vector procedures

7.4.1: vector-map

  • (vector-map proc vector1 vector2) procedure
Restrictions

The proc must accept as many values as there are vectors and return a single value.

Semantics

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 proc is always called in the same dynamic environment as the call to vector-map. 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.

Compatability Note: The R6RS version of this procedure did not allow the vectors to be of different lengths. The behavior here is from the R7RS-Small.

Examples
(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)))unspecified
either #(1 2)
or #(2 1)

7.4.2: vector-for-each

  • (vector-for-each proc vector1 vector2) procedure

[phm]: R6RS with some R7RS

Restrictions

The proc must accept as many arguments as there are vectorss, otherwise it is a domain error. It is undefined behavior for proc to mutate any of the vectors.

Semantics

Applies proc element-wise to the elements of the vectorss for its side effects, in order from the first elements to the last. The proc always called in the same dynamic environment as the call to vector-for-each. 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.

This procedure returns an unspecified value.[phm]: Unspecified values?

Compatability Note: The R6RS version of this procedure did not allow the vectors to be of different lengths. The behavior here is from the R7RS-Small.

Examples
(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)

8: 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 indexes of a bytevector are the exact non-negative integers less than the length of the bytevector, starting at index zero as with vectors.

The grammar of bytevectors is

byte
::= any exact integer between 0 inclusive and 255 inclusive
bytevector
::= #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.

8.1: Fundamental bytevector procedures

8.1.1: bytevector?

  • (bytevector? obj) procedure
Description

Returns #t if obj is a bytevector. Otherwise, #f is returned.

8.1.2: make-bytevector

  • (make-bytevector k [fill]) procedure
Restrictions

It is a domain error if fill, when present, is not in [-128,255].

Description

Returns a newly allocated bytevector of length k. If fill is given, then all elements of the bytevector are initialized to fill, otherwise the contents of each element are unspecified.

If fill is negative, then the bytevector is filled with the twos compliment representation of that negative number.

Compatability Note: The behavior when fill is negative comes from the R6RS.

Examples
(make-bytevector 2 12)#u8(12 12)

8.1.3: bytevector

  • (bytevector byte) procedure
Description

Returns a newly allocated bytevector whose elements are the given arguments. It is analogous to list.

Examples
(bytevector 1 3 5 1 3 5)#u8(1 3 5 1 3 5)
(bytevector)#u8()

8.1.4: bytevector=?

  • (bytevector=? bytevector1 bytevector2 bytevector3) procedure
Description

Returns #t if all bytevectors are the same—that is, they have the same length and have equal bytes at all valid indices.

Compatability Note: This is an extension of the procedure in the R6RS Standard Libraries.

8.1.5: bytevector-length

  • (bytevector-length bytevector) procedure
Description

Returns the length of bytevector in bytes as an exact integer.

Examples
(bytevector-length #u8(1 1 2 3 5 8 13 21))8

8.1.6: bytevector-u8-ref

  • (bytevector-u8-ref bytevector k) procedure
Restrictions

It is a domain error if k is not a valid index of bytevector.

Description

Returns the kth byte of bytevector.

Examples
(bytevector-u8-ref #u8(1 1 2 3 5 8 13 21) 5)8

8.1.7: bytevector-u8-set!

  • (bytevector-u8-set! bytevector k byte) procedure
Restrictions

It is a domain error if k is not a valid index of bytevector.

Description

Stores byte as the kth byte of bytevector.

Examples
(let ((bv (bytevector 1 2 3 4)))
  (bytevector-u8-set! bv 1 3)
  bv)#u8(1 3 3 4)

8.2: Bulk bytevector procedures

8.2.1: bytevector-copy

  • (bytevector-copy bytevector [start [end]]) procedure
Description

Returns a newly allocated bytevector containing the bytes in bytevector between start and end.

Examples
(define a #u8(1 2 3 4 5))
(bytevector-copy a 2 4))#u8(3 4)

8.2.2: bytevector-copy!

  • (bytevector-copy! to at from [start [end]]) procedure
Restrictions

It is a domain error if to and from are not bytevectors. It is a domain error if at is less than zero or greater than the length of to. It is a domain error if (- (bytevector-length to) at) is less than (- end start).

Description

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.

Compatability Note: This procedure appears in the R6RS, but places the source before the destination, contrary to other such procedures in Scheme.

Examples
(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)

8.2.3: bytevector-append

  • (bytevector-append bytevector) procedure
Description

Returns a newly allocated bytevector whose elements are the concatenation of the elements in the given bytevectors.

Examples
(bytevector-append #u8(0 1 2) #u8(3 4 5))#u8(0 1 2 3 4 5)

9: Number vectors

Number vectors are homogenous, fixed-length blocks of certain types of numbers. A number vector is typically more efficient than a vector containing numbers of the specified type. They are:

Bytevectors and u8vectors are the same type of object.

Number vectors may be written according to the following parameterized grammar:

n
::= s8
::= u8
::= s16
::= u16
::= s32
::= u32
::= s64
::= u64
::= f32
::= f64
::= c64
::= c128
number vector (prefix)
::= #prefix(elements valid for (prefix)

The length of a number vector is the number of elements that it contains. The valid indexes of a number vector are the exact non-negative integers less than the length of the number vector, starting at index zero.

Number vector constants are self-evaluating, so they do not need to be quoted in programs.

9.1: Number vector procedures

For simplicity, n is used in the name of procedures to describe procedures defined for all possible types of number vector.

9.1.1: make-nvector

  • (make-nvector size [nelem]) procedure
Description

Returns an nvector whose length is size. If nelem is provided, all the elements of the nvector are initialized to it.

Examples
(make-s8vector 5 -1)#s8(-1 -1 -1 -1 -1

9.1.2: nvector

  • (nvector nelem) procedure
Description

Returns a nvector initialized with nelems.

Examples
(f64vector 2.0 4.0)#f64(2.0 4.0)

9.1.3: nvector?

  • (nvector? obj) procedure
Description

Returns #t if obj is an nvector, and #f otherwise.

Examples
(f32vector? #f32(1.0 2.0))
#t
(f64vector? #f32(1.0 2.0))
#f

9.1.4: n?

  • (n? obj) procedure
Description

Returns #t if obj is a valid element of an nvector, and #f otherwise.

Examples
(s8? -128)#t
(s8? (abs -128))#f

9.1.5: nvector-length

  • (nvector-length nvector) procedure
Description

Returns the length of the nvector.

Examples
(u32vector-length #u32(100 200 300))#t

9.1.6: nvector-ref

  • (nvector-length nvector k) procedure
Restrictions

It is a domain error if k is not a valid index of nvector.

Description

Returns the kth element of nvector.

Examples

This section assumes that the stored c64 numbers can be round-tripped.

(c64vector-ref #c64(1.0+2.0i 3.0+4.0i) 0)1.0+2.0i

9.1.7: nvector-set!

  • (nvector-set! nvector k nelem) procedure
Restrictions

It is a domain error if k is not a valid index of nvector.

Description

Sets the kth element of nvector to be nelem.

Examples

This section assumes that the stored c64 numbers can be round-tripped.

(let ((v (make-c64vector 2 1.0+1.0i)))
  (c64vector-set! v 0 2.0+2.0i)
  v)#c64(2.0+2.0i 1.0+1.0i)

9.1.8: nvector->list

  • (nvector->list nvector [start [end]]) procedure
Description

Returns a list whose elements are the elements of nvector between start and end.

Examples
(u8vector->list #u8(#xFE #xFF 10 20 30) 2 4)(#xFF 10)

9.1.9: list->nvector

  • (list->nvector list [start [end]]) procedure
Restrictions

It is a domain error if the elements of list between start and end are not allowed elements of an nvector.

Description

Returns a nvector whose elements are the elements of list between start and end.

Examples
(list->u8vector '(#xFE #xFF 10 20 30) 2 4)#u8(#xFF 10)