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.

6.1  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:

The eqv? procedure returns #f if:

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

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

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

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

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

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

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

6.2.6  Numerical operations

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 −1 z, cos −1 z, and tan −1 z are according to the following formulæ:

sin −1 z = −i log (i z + (1 − z2)1/2)

cos −1 z = π/ 2 − sin −1 z

tan −1 z = (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.

6.2.7  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 [45]; 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.

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

6.4  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 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
⟹ (3 8 2 8)
⟹ (1 8 2 8)

6.5  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

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

6.7  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 (\):

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)
⟹ "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.

6.8  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
⟹ #(3 8 2 8)
(define c (vector-copy b 1 3))
⟹ #(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)
⟹ #(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)

⟹ #(1 2 smash smash 5)

6.9  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)
⟹ #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)

6.10  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:

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)

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

6.12  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

6.13  Input and output

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

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

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

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