Chapter 4
Scheme Reference
This chapter is a reference manual for the Scheme programming language. Don't read this chapter to learn Scheme, but turn to it when you need more detail about the language than appears in Structure and Interpretation of Computer Programs [1].
4.1 Notation and terminology
This section describes the notation used in this chapter. It also discusses the lexical conventions for writing Scheme program
4.1.1 Notation for this Chapter
In this chapter, in text describing a procedure or special form, the names of all formal parameters are italicized. The names of Scheme procedures, special forms, and variables appear in typewriter-style type. Throughout the chapter, whenever a formal parameter has one of the names listed in the left column of the table below, it must be of the type listed in the right column. For example, a formal parameter referred to as n2 in this chapter must be an integer.
57
58 CHAPTER 4. SCHEME REFERENCE
obj any object
x, x1,... xj,... real number
y, y1,... yj,... real number
n, n1,... nj, integer
k, k1,... kj, nonnegative integer
4.1.2 Evaluation
The symbol "==>" in these examples means "evaluates to." For example,
(+ 5 8) ==> 40
means that the expression (+ 5 8) evaluates to 40.
Where the value returned by an expression is marked unspecified, Scheme does not guarantee what the value will be. For example,
(set! x 3) ==> unspecified
Feel free to experiment to determine what Scheme returns in any particular case, but remember that a new version of Scheme might return a different value. Avoid writing programs that rely on unspecified values, particularly when working on problem sets.
4.1.3 Numbers
Scheme numbers are expressed exactly as normal numbers, except that scientific notation looks slightly different. In Scheme scientific notation, the numbers of the exponent are not raised, but instead are separated from the base number by the letter e. For example,
123e10 is
Scheme notation for 123 x 1010, and -123.45e-1 is Scheme notation for -123.45 x 10-1.4.1. NOTATION AND TERMINOLOGY 59
4.1.4 Identifiers
A Scheme identifier is a sequence of letters, digits, and punctuation characters that is not a number. Here are some identifiers:
|
lambda |
q |
<=? |
|
list->vector |
soup |
a34kTMNs |
|
+ |
V17a |
the-word-recursion-has-many-meanings |
Upper and lower case forms of a letter are never distinguished except within character and string constants. For example, Foo is the same identifier as FOO.
Identifiers have several uses within Scheme programs:
• Certain identifiers are reserved for use as special forms, and cannot be used as variables. They are:
|
and |
else |
or |
|
begin |
error |
quote |
|
cond |
if |
sequence |
|
cons-stream |
lambda |
set! |
|
define |
let |
the-environment |
|
delay |
make-environment |
unquote |
• Any identifier that does not refer to a special form may be used as a variable (see section 4.2 ).
• When an identifier appears as a quoted constant or within a quoted constant, it denotes a symbol (see section 4.7 ).
4;1.5 Whitespace and Comments
Whitespace characters are spaces and line breaks (newlines). Whitespace is used to improve readability and to separate tokens (identifiers and numbers) from each other. Whitespace may also occur inside a string value.
A semicolon starts a comment, text which will be seen as whitespace by Scheme. The comment continues from the semicolon to the end of the line. For example:
60 CHAPTER 4. SCHEME REFERENCE
;; The FACT procedure computes the factorial
;; of a nonnegative integer.
(define fact
(lambda (n )
(if(= (n ) 0)
1 ;Base case: return 1
(* (n ) (fact (- (n ) 1))))))
4.1.6 Special Characters in Scheme Notations
Here are the special characters used in Scheme notations:
/ < = > ! ? : $ % _ & ~ ^
These characters may be used in identifiers as if they were letters.
. + -
These appear in numbers and identifiers. The period character is also used in the notation for pairs (section 4.6 ).
( )
Parentheses surround expressions and lists (section 4.6 ).
'
The single quote character indicates literal data (section 4.3.2 ).
"
Double quote characters surround string values (section 4.9 ).
\
Backslash is an escape character within string constants (section 4.9 ).
[ ] { }
Left and right square brackets and curly braces are reserved for possible future extensions to the language.
#t #f
These are the boolean constants true and false (section 4.5 ).
#\
Represents the ASCII standard number representing the immediately following character.
#(
Introduces a vector constant (section 4.10).
4.2. VARIABLES AND BINDINGS 61
Variables and bindings
Any identifier that does not refer to a special form (see section 4.1.4 ) may be used as a variable. A variable may name a location where a value can be stored. A variable that does so is said to be bound to the location. The set of all bindings in effect at some point in a program is the environment.
Certain expressions create new locations and bind variables to them. The most fundamental of these binding constructs is the lambda expression, because all other binding constructs can be explained in terms of lambda expressions. See section 4.3.5.
Like Algol and Pascal, and unlike most other dialects of Lisp except Common Lisp, Scheme is statically scoped and has block structure. To each place where a variable is bound in a program there corresponds a region of the program text within which the binding is effective. The region is determined by the particular binding construct that establishes the binding; if the binding is established by a lambda expression, for example, then its region is the entire lambda expression. Every reference to or assignment of a variable refers to the binding of the variable that established the innermost of the regions containing the use. If there is no binding of the variable whose region contains the use, then the use refers to the binding for the variable in the top level environment; if there is no binding for the identifier, it is said to be unbound.
Expressions
A Scheme expression is a piece of code that returns a value. Types of expressions include variable references, literals, procedure calls, and special forms (see section 4.1.4 ). This section describes all Scheme expression types except conditionals and logical operations, which are described in section 4.5.
4.3.1 Variable references
variable syntax
An expression consisting of a variable (section 4.2 ) is a variable reference. The value of the variable reference is the value stored in the location to which the variable is bound. It is an error to reference an unbound variable.
(define x 28)
x ==> 28
62
CHAPTER 4. SCHEME REFERENCE
x
4.3.2 Literals
(quote
datum) syntax' datum syntax
constant syntax
(quote
datum) evaluates to datum. Datum may be any printed representation of a Scheme object. This notation is used to include literal constants in Scheme code.(quote a) ==> a
(quote #(a b c )) ==> #(a b c)
(quote (+ 1 2 )) ==> (+ 1 2)
(quote
datum) may be abbreviated as datum. The two notations are equivalent in all respects.'a ==> a
'#(a b c) ==> #(a b c)
'(+ 1 2) ==> (+ 1 2)
'(quote a) ==> (quote a)
''a ==> (quote a)
Numeric constants, string constants, character constants, and boolean constants evaluate "to themselves"; they need not be quoted.
'"abc" ==> "abc"
'145932 ==> 145932
'#t ==> #t
#t ==> #t
4.3. EXPRESSIONS 63
4.3.3 Procedure calls
(operator operand1, ... ) syntax
A procedure call is written by enclosing in parentheses expressions for the procedure to be called and the arguments to be passed to it. The operator and operand expressions are evaluated (in an indeterminate order) and the resulting procedure is passed the resulting arguments.
(+ 3 4) ==> 7
((if #f + *) 3 4) ==> 12
Procedure calls are also called combinations.
4.3.4 Lambda expressions
(lambda formals body) syntax
Syntax: Formals should be a formal arguments list as described below,
and body should be a sequence of one or more expressions.
Semantics: A lambda expression evaluates to a procedure. The environment in effect when the lambda expression was evaluated is remembered as part of the procedure. When the procedure is later called with some actual arguments, the environment in which the lambda expression was evaluated will be extended by binding the variables in the formal argument list to fresh locations, the corresponding actual argument values will be stored in those locations, and the expressions in the body of the lambda expression will be evaluated sequentially in the extended environment. The result of the last expression in the body will be returned as the result of the procedure call.
(lambda
( x ) (+ x x)) ==> a procedure((lambda (x) (+ x x)) 4) ==> 8
(define reverse-subtract
(lambda (x y ) (- y ) x)))
(reverse-subtract 7 10) ==> 3
(define foo
(let ((x 4 ))
(lambda (y) (+ x y))))
(foo 6) ==> 10
64 CHAPTER 4. SCHEME REFERENCE
Formals should have one of the following forms:
• (variable1, ... ): The procedure takes a fixed number of arguments; when the procedure is called, the arguments will be stored in the bindings of the corresponding variables.
• variable: The procedure takes any number of arguments; when the procedure is called, the sequence of actual arguments is converted into a newly allocated list, and the list is stored in the binding of the variable.
• (variable1, ... variablen-1, . variablen): If a period surrounded by spaces precedes the last variable, then the value stored in the binding of the last variable will be a list of the actual arguments left over after all the other actual arguments have been matched up against the formal arguments.
((lambda x x) 3 4 5 6) ==>
(3 4 5 6)((lambda (x y . z) z) 3 4 5 6) ==>
(5 6)4.3.5 Binding constructs
The binding construct let gives Scheme a block structure, like Algol 60. The syntax of the three constructs is identical, but they differ in the regions they establish for their variable bindings. In a let expression, the initial values are computed before any of the variables become bound.
(let bindings body) syntax
Syntax: Bindings should have the form
((variable, init1 ) ... ).
where each init is an expression, and body should be a sequence of one or more expressions.
Semantics: The inits are evaluated in the current environment (in some unspecified order), the variables are bound to fresh locations holding the results, the body is evaluated in the extended environment, and the value of the last expression of body is returned. Each binding of a variable has body as its region.
(let (( x 2) ( y 3))
(* x y)) ==> 6
(let (( x 2) ( y 3))
(let ((foo (lambda (z) (+ x y z)))
(x 7))
(foo 4 ))) ==> 9
4.3. EXPRESSIONS 65
(let
variable bindings body) syntaxThis is an extension of the syntax of let, called "named let" which provides a general looping construct and which may also be used to express recursions.
Named let has the same syntax and semantics as ordinary let except that variable is bound within body to a procedure whose formal arguments are the bound variables and whose body is body. Thus the execution of body may be repeated by invoking the procedure named by variable.
(let loop ((numbers '((3 -2 1 6 5))
(nonneg '() )
(neg '() ))
(cond ((null? numbers) (list nonneg neg))
((>= (car numbers) 0)
(loop (cdr numbers)
(cons (car numbers) nonneg)
neg))
((< (car numbers) 0)
(loop (cdr numbers)
nonneg
(cons (car numbers) neg)))))
==> ( 6 1 3) (-5 -2)
4.3.6 Assignments
(set!
variable expression) syntaxExpression is evaluated, and the resulting value is stored in the location to which variable is bound. Variable must be bound in some region or at top level. The result of the set! expression is unspecified.
(define x 2) ==>
unspecified(+ x 1) ==> 3
(set! x 4) ==>
unspecified(+ x 1) ==> 5
66 CHAPTER 4. SCHEME REFERENCE
4.3.7 Sequencing
(sequence expression, expression2 ... ) syntax
The expressions are evaluated sequentially from left to right, and the value of the last expression is returned. This expression type is used to sequence side effects such as input and output.
(sequence (set! x
5)(+ x 1 )) ==> 6
(sequence (princ "4 plus I equals ")
(princ (+ 4
1 ))) ==> unspecifiedand prints 4 plus I equals 5
Note: Sequence is a synonym for the begin sequencing construct of the Scheme standard.
4.4 Definitions
Definitions are used to establish bindings. Definitions are not valid in all contexts where expressions are allowed. They are valid only at the top level of a program and at the beginning of a body. A definition should have one of the following forms:
(define
variable(lambda
(formals) body)).(define
variable(lambda formal body)),
4.4. DEFINITIONS 67
4.4.1 Top level definitions
At the top level of a program, a definition
(define
variable expression)has essentially the same effect as the assignment expression
(set!
variable expression)if variable is bound. If variable is not bound, however, then the definition will bind variable to a new location before performing the assignment, whereas it would be an error to perform a set! on an unbound variable.
(define add3
(lambda
( x ) (+ x 3 )))(add3 3) ==> 6
(define first car)
(first '(1 2)) ==> 1
4.4.2 Internal definitions
Definitions are also permitted at the beginning of a body (that is, the body of a lambda, let, or define expression). Such definitions are known as internal definitions as opposed to the top level definitions described above. The variable defined by an internal definition is local to the body. That is, variable is bound rather than assigned, and the region of the binding is the entire body. For example,
(let ((x 5))
(define foo (lambda (y) (bar x y)))
(define bar (lambda (a b) (+ (* a b) a)))
(foo (+ x 3 ))) ==> 45
68 CHAPTER 4. SCHEME REFERENCE
Booleans and conditionals
The standard boolean objects for true and false are written as #t and #f. t and nil are alternative ways of writing #t and #f, respectively. What really matters, though, are the objects that the Scheme conditional expressions (if, cond, and, or) treat as true or false. The phrase "a true value" (or sometimes just "true") means any object treated as true by the conditional expressions, and the phrase "a false value" (or "false") means any object treated as false by the conditional expressions.
Of all the standard Scheme values, only #f and the empty list 0 count as false in conditional expressions. Everything else, including #t, pairs, symbols, numbers, strings, vectors, and procedures, counts as true.
Boolean constants evaluate to themselves, so they don't need to be quoted in programs.
#t ==>
#t#f ==> #f
'#f ==> #f
true
variablefalse
variableThe variables true and false are initially bound to the values #t and #f respectively. Note that these are ordinary variables, whereas #t and #f are constants.
true ==>
#tfalse ==>
#f'false ==> false
Boolean operations
(not obj ) procedure
Not returns #t if obj is false, and returns #f otherwise.
(not #t) ==>
#f(not 3) ==>
#f(not (list 3)) ==>
#f(not #f ) ==>
#t(not '() ) ==>
#t(not (list)) ==>
#t4.5. BOOLEANS AND CONDITIONALS 69
(and
test1, ... ) syntaxThe test expressions are all evaluated. And returns #f if any of its arguments is false, and #t otherwise.
(and (< 3 4) (> 6 5)) ==>
#t(and (> 3 4) (> 6 5)) ==>
#f(and) ==>
#t ; by convention(or
test1, ... ) syntaxThe test expressions are all evaluated. Or returns #t if any of its arguments is true, and #f otherwise.
(or (eq? 'x 'y )
(eq? 'z 'y )) ==> #f(or (> x 0) (= x 0) (< x 0 )) ==>
#t(or) ==>
#f ; by convention(conjunction
test, ... ) syntaxThe test expressions are evaluated from left to right, and the value of the first expression that evaluates to a false value is returned. Any remaining expressions are not evaluated. If all the expressions evaluate to true values, the value of the last expression is returned. If there are no expressions then #t is returned.
(conjunction (= 2 2) (> 2 1 )) ==>
#t(conjunction (= 2 2) (< 2 1 )) ==>
#f(conjunction) ==>
#t70 CHAPTER 4. SCHEME REFERENCE
(disjunction test, syntax
The test expressions are evaluated from left to right, and the value of the first expression that evaluates to a true value is returned. Any remaining expressions are not evaluated. If all expressions evaluate to false values, the
(false) value of the last expression is returned. If there are no expressions then #f is returned.
(disjunction (= 2 2) (> 2 1 ))
==> #t(disjunction (= 2 2) (< 2 1 ))
==> #t(disjunction #f #f
#f ) ==> #f(disjunction (memq 'b '(a b
c)) (/ 3 0)) ==> (b c)(disjunction)
==> #f4.5.2 Conditionals
(if test consequent alternate) syntax
(if test consequent) syntax
Syntax: Test, consequent, and alternate may be arbitrary expressions.
Semantics: An if expression is evaluated as follows: first, test is evaluated. If it yields a true value (see section 4.5), then consequent is evaluated and its value is returned. Otherwise alternate is evaluated and its value is returned. If test yields a false value and no alternate is specified, then the result of the expression is unspecified.
(if (> 3 2) 'Yes 'no) ==> yes
(if (> 2 3) 'Yes 'no) ==> no
(if (> 3 2)
(- 3 2)
(+ 3 2)) ==> 1
4.5. BOOLEANS AND CONDITIONALS - 71
(cond
clause1 clause2 …) syntaxSyntax: Each clause should be of the form
(test expression …)
where test is any expression. The last clause may be an "else clause," which has the form
(else
expression1 expression2 … )Semantics: A cond expression is evaluated by evaluating the test expressions of successive clauses in order until one of them evaluates to a true value (see section 4.5 ). When a test evaluates to a true value, then the remaining expressions in its clause are evaluated in order, and the result of the last expression in the clause is returned as the result of the entire cond expression. If the selected clause contains only the test and no expressions, then the value of the test is returned as the result. If all tests evaluate to false values, and there is no else clause, then the result of the conditional expression is unspecified; if there is an else clause, then its expressions are evaluated, and the value of the last one is returned.
(cond ((> 3 2) 'greater)
((< 3 2) less)) ==> greater
(cond ((> 3 3) 'greater)
((< 3 3) less)
(else 'equal)) ==> equal
72 CHAPTER 4. SCHEME REFERENCE
4.5.3 Testing for equivalence
The three predicates described in this section are used to test whether objects are "the same". Of the three predicates, eq? is the finest or most discriminating while equal? is the coarsest. Eqv? is slightly less discriminating than eq?. In general, you should use equal? to test the equivalence of structures and eqv? to test the equivalence of atomic objects. See [2] for a careful description of the rationale for these three different predicates.
(eq?
obj1 obj2) procedureEq? is the primitive equivalence predicate. It returns true if obj1 and obj2 are the same object. Unless you are rather advanced, do not use eq? to test identity of objects other than symbols. In particular, two numbers which are equal in value may not be eq?; use = or eqv? to test numerical equality. Also, two lists which have the same elements and print the same may not be eq?; use equal? to test if lists have the same elements.
For more advanced users only: Two structures are eq? if any attempt to modify one of them modifies the other in the same way; i.e., if the two structures share the same location in memory.
(define x '(a b))
==> X(define y '(a b))
==> Y(define z x)
==> Z(eq? x y)
==> #f(eq? x z)
==> #t(eq? y z)
==> #f(set! x 'foo)
==> unspecified(set! y 'foo)
==> unspecified(set! z x)
==> unspecified(eq? x y)
==> #t(eq? x z)
==> #t(eq? y z)
==> #t
4.5. BOOLEANS AND CONDITIONALS 73
(eqv?
obj1 obj2) procedureEqv? returns #t if obj1 and obj2 are: eq? atoms, = numbers, or character strings containing the same characters in the same order with the same capitalization. Two lists are not in general eqv? even if eq? atom by atom. Eqv? is usually the correct predicate for testing the equality of atoms.
(eqv? "abc" "abc") ==> #t
(eqv? '(a b c) '(a b c)) ==> #f
(eqv? 67000 67000) ==> #t
(let ((a '(1 2 3)))
(let ((b (cons a a))
(eqv? (car b) (cdr b)))) ==> #t
(eqv? (lambda () 1)
(lambda () )) ==> #f
(let ((p (lambda () 1)))
(eqv? p p)) ==> #t
(equal?
obj1 obj2) procedureEqual? returns #t if both arguments are eqv? atoms, numbers, or character strings. Equal? list structures are those whose CARs are equal? and whose CDRs are equal?. As illustrated below, eq? and equal? are quite different.
(eq? '(a b) '(a b)) ==> #f
(equal? '(a b) '(a b)) ==> #t
(define x '(a b)) ==> X
(define y '(a b )) ==> y
(equal? x y ==> #t
(equal? 3 3) ==> #t
(equal? 67000 67000) ==> #t
(equal? "abc" "abc") ==> #t
74 CHAPTER 4. SCHEME REFERENCE
4.6 Pairs and lists
A pair is a structure with two fields called the car and cdr fields (for historical reasons). Pairs are constructed by the procedure cons. The car and cdr fields are accessed by procedures car and cdr, and set by procedures set-car! and set-cdr!.
Pairs are used primarily to represent lists. A list is either empty or a pair whose car is the first element of the list, and whose cdr is the rest of the list. The length of a list is the number of elements, which is the same as the number of pairs.
The empty list is a special object of its own type (it is not a pair); it has no elements and its length is zero.
The most general notation 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 list is written (). For example,
(a b c d e)
and
(a . (b . ( c . (d . (e . ())))))
are both representations of a list of (the same) 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)))
4.6. PAIRS AND LISTS 75
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)
(set-cdr! x 4) ==>
unspecifiedx ==> (a 4)
(eqv? x y) ==> #t
y ==> (a 4)
(atom? obj) procedure
Returns #t if obj is an atom, and #f otherwise. An atom is anything which cannot be further decomposed via car or cdr. In other words, anything that is not a pair is an atom.
(atom? 3) ==> #t
(atom? 'car) ==> #t
(atom? car) ==> #t
(atom? '(a 3)) ==> #f
(atom? '()) ==> #t
(atom? nil) ==> #t
(list? obj)
Returns #t if obj is a list, and #f otherwise.
(list? 'a) ==> #f
(list? 1 '() ) ==> #t
(list? '(a b)) ==> #t
(list? '(a . b)) ==> #f
(pair?
obj) procedureReturns #t if obj is a pair, and #f otherwise. Note that the empty list, '() ) is a list but not a pair.
(pair? (a . b))
(pair? (a b
c )) ==> #t(pair? '() )
==> #f(pair? '#(a b))
==> #f76 CHAPTER 4. SCHEME REFERENCE
(cons
obj1 obj2) procedureReturns 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)
(car pair) procedure
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
(cdr pair) procedure
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
4.6. PAIRS AND LISTS 77
(set-car!
pair obj) procedureStores obj in the car field of pair. The value returned by set-car! is unspecified.
(set-cdr!
pair obj) procedureStores obj in the cdr field of pair. The value returned by set-cdr! is unspecified.
(caar
pair) procedure(cadr
pair) procedure(cdddar
pair) procedure(cddddr
pair) procedureThese procedures are compositions of car and cdr, where for example caddr could be defined by
(define caddr (lambda ( x ) (car (cdr (cdr x )))))
Arbitrary compositions, up to four deep, are provided. There are twenty-eight of these procedures in all.
(first
pair) procedure(second
pair) procedure(third
pair) procedure(fourth
pair) procedure(fifth
pair) procedure(sixth
pair) procedure(seventh
pair) procedure(eighth
pair) procedureThese procedures return the first, second, third, ..., eighth element of pair, respectively, in exactly the same manner as would car, cadr, caddr, cadddr, ....
(first '((a b) c d)) ==> (a b)
(second '((a b) c d)) ==> c
(eighth '(a b c d e f g h )) ==> h ))
78 CHAPTER 4. SCHEME REFERENCE
(null?
obj) procedureReturns #t if obj is the empty list, otherwise returns #f.
(list
obj, ... ) procedureReturns a list of its arguments.
(list 'a (+ 3 4) 'c) (list) ==> (a 7 c)
(list) ==> ()
(list* obj1 obj2 … ) procedure
List* cons
es together an arbitrary number of arguments. It constructs a pair whose car is obj, and whose cdr is (list* obj2 ... ). When it has only two arguments, list* behaves in the same way as cons.(list* 'a 'b 'c) ==> (a b . c)
(list* '(a b) c '(d e)) ==> ((a b) c d e)
(list* a 'b) ==> (a . b)
(list* 'a) ==> a
(length list) procedure
Returns the length of list.
(length '(a b c)) ==> 3
(length '(a (b) (c d e))) ==> 3
(length
'()) ==> 0
(append list1 list2 ) (append list ... ) procedure
(append list … ) procedure
Returns a list consisting of the elements of the first list followed by the elements of the other lists.
(append '(x) '(y)) ==> (x y)
(append '(a) '(b c d)) ==> (a b c d)
(append '(a (b)) ((c))) ==> (a (b) (c))
The resulting list is always newly allocated, except that it shares structure with the last list argument. The last argument may actually be any object; an improper list results if it is not a proper list.
(append '(a b) '(c . d)) ==> (a b c . d)
(append '() 'a) ==> a
4.6. PAIRS AND LISTS 79
(reverse
list) procedureReturns 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)
(list-tail list k) procedure
(nthcdr k list)
procedureReturns the sublist of list obtained by omitting the first k elements. List-tail could be defined by
(define list-tail
(lambda (x k)
(if (zero? k)
x
(list-tail (cdr x) (- k 1)))))
For historical reasons, (nthcdr k list) is the same as (list-tail list k)
(list-tail '(a b c d) 2) ==> (c d)
(nthcdr 2 '(a b c d)) ==> (c d)
(last list) procedure
Returns the last pair of list.
(last '(a b
c)) ==> (c)80 CHAPTER 4. SCHEME REFERENCE
(list-ref
list k) procedure(nth
k list) procedureBoth list-ref and nth return the kth element of list, where numbering starts with zero. (This is the same as the car of (list-tail list k).)
(list-ref '(a b c d) 2) ==> c
(nth 2 '(a b c d)) ==> c
(member obj list) procedure
(memq
obj list) procedure(memv
obj list) procedureReturns the first sublist of list whose car is obj. If obj does not occur in list, returns #f. Memq uses eq? to compare obj with the elements of list, while memv uses eqv? and member uses equal?.
(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))(memq 101 '(100 101 102) ==>
unspecified(memv 101 '(100 101 102) ==> (101 102)
(assoc obj alist) procedure
(assq obj alist) procedure
(assv obj alist) procedure
Alist (for "association list") must be a list of pairs. Finds the first pair in alist whose car field is obj and returns that pair. If no pair in alist has obj as its car, returns #f. Assq uses eq? to compare obj with the car fields of the pairs in alist, while assv uses eqv? and assoc uses equal?.
(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
(assq 5 1((2 3) (5 7) (11 13))) ==> unspecified
(assv 5 '((2 3) (5 7) (11 13))) ==> (5 7)
(assoc (list 'a) (( c )))) ((b)) (( c )))) ==> (( c ))))
Note: Although they are ordinarily used as predicates, memq, memv, member, assq, assv, and assoc do not have question marks in their names because they return useful values rather than just #t or #f.
4.7 SYMBOLS 81
4.7 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. The rules for writing a symbol are exactly the same as the rules for writing an identifier; see section 4.1.4.
(symbol?
obj) procedureReturns #t if obj is a symbol, otherwise returns #f.
(symbol? 'foo) ==> #t
(symbol? (car (a (( c )))) ==> #t
(symbol? "bar") ==> #f
(alphaless? symbol1 symbol2 ) procedure
Returns #t or #f according to whether the name of symbol1 alphabetically precedes the name of symbol2
(alphaless? lab 'b) ==> #t
(alphaless? 'a 'a) ==> #f
(explode symbol) procedure
Returns a list of one-character symbols or digits that are the letters in the name of symbol.
(explode 'gleep35) ==> (G L E E P 3 5)
(implode
list) procedureThe argument must be a list of character symbols or integers. Implode returns a symbol whose name is the concatenation of the names of elements in list.
(implode '(g 1 e e p 3 5)) ==> GLEEP35
(char n) procedure
Returns the ASCII character (symbol) whose ASCII code is n.
(char 65) ==> A
(
ascii symbol) procedureReturns the ASCII code of the single-character symbol symbol. All alphabetic characters are regarded as upper case, because symbols do not retain the case in which they are typed.
(ascii 'a) ==> 65
(generate-uninterned-symbol symbol) procedure
Returns a symbol that is guaranteed to be different (not eqv?) from any other symbol. The printed representation of the new symbol will begin with the characters of symbol. Note: The "name" of an uninterned symbol is convenience for the human reader. You cannot reference an uninterned symbol by quoting its name.
(define s (generate-uninterned-symbol 'fact)) ==>
unspecifieds ==>
something of the form FACT342(eqv? s s) ==> #t
(eqv? s 'FACT342) ==> #f
4.8 NUMBERS 83
4.8 Numbers
Section 4.1.1 lists the names used here to specify restriction on the types of arguments these numerical procedures will accept.
(number?
obj) procedure(integer?
obj) procedureThese numerical type predicates can be applied to any kind of argument, including non-numbers. They return true if the object is of the named type. In general, if a type predicate is true of a number then all higher type predicates are also true of that number.
(zero? z)
procedure(positive? x)
procedure(negative? x)
procedure(odd?
n) procedure(even?
n) procedureThese numerical predicates test a number for a particular property, returning #t or #f.
(= z1 z2) procedure
(<
x1 x2) procedure(>
x1 x2) procedure(<=
x1 x2) procedure(>=
x1 x2) procedureThese procedures return #t if their arguments are (respectively): numerically equal, monotonically increasing, monotonically decreasing, monotonically nondecreasing, or monotonically nonincreasing.
94 CHAPTER 4. SCHEME REFERENCE
(max
x1 x2) procedure(max
x1 x2 … ) procedure(min
x1 x2) procedure(min
x1 x2 … ) procedureThese procedures return the maximum or minimum of their arguments.
(+
z1 z2) procedure(+
z1 … ) procedure(*
z1 z2) procedure(*
z1 … ) procedureThese procedures return the sum. or product of their arguments.
(+ 3 4) ==> 7
(+ 3) ==> 3
(+) ==> 0
(* 4) ==> 4
(*) ==> 1
(- z1 z2) procedure
(-
z1 z2 … ) procedure(/
z1 z2) procedure(/
z1 z2 …) procedureWith 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.
(- 3 4) ==> -1
(- 3 4 5) ==> -6
(- 3) ==> -3
(/ 3 4 5) ==> 3/20
(/ 3) ==> 1/3
4.8. NUMBERS 85
(1+ z)
procedureThis procedure returns a value one greater than its argument.
(1+ 3) ==> 4
(-1+ z) procedure
This procedure returns a value one less than its argument.
(-1+ 3) ==> 2
(abs z) procedure
Abs returns the magnitude of its argument.
(abs -7) ==> 7
(abs -3+4i) ==> 5
(quotient n1 n2) procedure
(remainder
n1 n2) procedure(integer-divide
n1 n2) procedureThese are intended to implement number-theoretic (integer) division: For
positive integers n1 and n2, if n3 and n4 are integers such that n1 = n2 n3 + n4
and 0 < n4 < n2, then
(quotient
n1 n2) n3(remainder
n1 n2) n4(integer-divide
n1 n2) (n3 n4)integer-divide returns the cons of what quotient and remainder would return given the same arguments.
For all integers n1 and n2 with n2 not equal to 0,
(=
n1 (+ (* n2 (quotient n1 n2)) (remainder n1 n2))) ==> #tThe value returned by quotient always has the sign of the product of its arguments. Remainder always has the sign of the dividend.
(remainder 13 4) ==> 1
(remainder -13 4) ==> -1
(remainder 13 -4) ==> 1
(remainder -13 -4) ==> -1
86 CHAPTER 4. SCHEME REFERENCE
(gcd
n1 … ) procedureThese 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
(floor x) procedure
(ceiling x) procedure
(truncate x) procedure
(round x) procedure
These procedures create integers and rationals.
Floor returns the largest integer not larger than x. Ceiling returns the smallest integer not smaller than x. Truncate returns the integer of maximal absolute value not larger than the absolute value of x. Round returns the closest integer to x, rounding to even when x is halfway between two integers. Note: Round rounds to even for consistency with the rounding modes required by the IEEE floating point standard.
(exp
z) procedure(log
z) procedure(sin
z) procedure(cos
z) procedure(tan
z) procedure(atan
y x) procedureLog
computes the natural logarithm of z (not the base 10 logarithm). Atan returns the arctangent, in radians, of the quotient of its arguments.For nonzero x, the value of log x is defined to be the one whose imaginary part lies in the range -p (exclusive) to p (inclusive). (Log 0) is undefined.
4.9. STRINGS 87
(sqrt
z) procedureReturns the square root of z.
(expt
z x ) procedureReturns z raised to the power x
zx = ex log z
00
is defined to be equal to 1.(random
k) procedureReturns an integer chosen at random between 0 and k-1, inclusive. The argument k must be a positive integer.
4.9 Strings
Strings are sequences of characters. Strings are written as sequences of characters enclosed within double quotes (") A double quote inside a string is created by \", as in
"The word \"recursion\" has many meanings."
88 CHAPTER 4. SCHEME REFERENCE
4.10 Vectors
Vectors are structures whose elements are indexed by integers. 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. The printed representation for vectors is a # followed by the sequence of elements, enclosed in parentheses. 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 following:
#(0 (2 2 2 2) "Anna")
Note that this is the external representation, not an expression evaluating to a vector. Like lists, vector constants must be quoted:
'#(0
(2 2 2 2) "Anna") ==> #(0 (2 2 2 2) "Anna")Vectors are created by the constructor procedures vector and vector-cons. The elements are accessed and assigned by the procedures vector-ref and vector-set!.
(vector? obj) procedure
Returns #t if obj is a vector, otherwise returns #f.
(vector-cons size fill) procedure
Vector-cons
returns a newly allocated vector of size elements, each initialized to fill.(vector
obj ... ) procedureReturns a newly allocated vector whose elements contain the given arguments. Analogous to list.
(vector 'a 'b 'c) ==> #(a b c)
(vector-size vector) procedure
Returns the number of elements in vector.
4.11. CONTROL FEATURES 89
(vector-ref
vector k) procedurek
must be a nonnegative integer less than (vector-length vector). vector-refreturns the contents of element k of vector.
(vector-ref '#(1 1 2 3 5 8 13 21) 5) ==> 8
(vector-set!
vector k obj) procedurek
must be a nonnegative integer less than (vector-length vector). Vector-set!stores obj in element k of vector. The value returned by vector-set! is unspecified.
(let ((vec (vector
0 '(2 2 2 2) "Anna" )))(vector-set! vec 1 '( "Sue" "Sue"))
vec)
==> #(0 ("Sue" ''Sue" ) "Anna")
4.11 Control features
This chapter describes various primitive procedures that control the flow of program execution in special ways.
(apply
proc args) procedureProc must be a procedure and args must be a list. Apply calls proc with the elements of 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
90 CHAPTER 4. SCHEME REFERENCE
(mapcar
proc list1 list2 ... ) procedureProc must be a procedure which takes as many arguments as there are lists supplied to mapcar. Mapcar returns a list whose first element is proc applied to the first element of each list, whose second element is proc applied to the second element of the list, and so on. Mapcar stops when it reaches the end of the shortest list.
(mapcar length '((a b) (c d) (e (f g) h))) ==> (2 2 3)
(mapcar +'(1 2 3) '(4 5 6)) ==> (5 7 9)
(mapcar *'(1 2) '(3 4 5) '(6 7 8 9)) ==> (18 56)
(mapc
proc list1 list2 ) procedureProc must be a procedure which takes as many arguments as there are lists supplied to mapc. Mapc applies proc to the first element of each list, to the second element of each list, and so on. The difference between mapc and mapcar is that mapcar returns a list of values, while mapc does not. The procedure proc is usually applied for effect, and the value returned by mapc should be ignored.
4.12 Streams and delayed evaluation
A stream is a structure with two fields called the head and the tail. Streams are created by cons-stream. The head and tail are accessed using the procedures head and tail. Streams are used for representing sequences of elements, which are retrieved as the heads of successive tails of the stream. In this way, a stream is like a list. The difference is that the items in the stream are delayed, that is, they are computed when they are accessed rather than when the stream is constructed. The empty stream is stream that has no elements. See chapter 3 of [1] for information on programming with streams.
4.12. STREAMS AND DELAYED EVALUATION 91
(cons-stream
obj1 obj2) syntaxReturns a stream whose head is obj1 and whose tail is obj2. Cons-stream is syntax rather than a procedure because it does not evaluate its second argument.
(head
stream) procedureReturns the head of the given stream.
(tail
stream) procedureReturns the tail of the given stream.
the-empty-stream
variableA variable initially bound to the empty stream.
(empty-stream?
obj) procedureReturns #t or #f depending on whether obj is the empty steam.
(delay
expression) syntaxThe delay construct, together with the procedure force, implement lazy evaluation or call by need. (delay expression) returns an object called a promise which at some point in the future may be asked (by the force
procedure) to evaluate expression and deliver the resulting value.
(force
promise), procedureForces the value of promise (see delay above). If no value has been computed for the promise, then a value is computed and returned. The value of the promise is cached (or "memoized") so that if it is forced a second time, the previously computed value is returned without any recomputation.
(force (delay (+ 1 2))) ==> 3
(let ((p (delay (+ 1 2))))
(list (force p) (force p)))
==> (3 3)
92 CHAPTER 4. SCHEME REFERENCE
Force
and delay are mainly intended for programs written using streams. The following examples should not be considered to illustrate good programming style, but they illustrate the property that the value of a promise is computed at most once.(define count 0)
(define p (delay (sequence (set! count (+ count 1))
(* x 3))))
(define x 5)
count ==> 0
p ==> a promise
(force p) ==> 15
p ==> a promise, still
count ==> 1
(force p) ==> 15
count ==> 1
4.13 Input and output
This chapter describes the procedures that are used for input and output (I/O). The chapter first describes "ports" and how they are manipulated, then describes the I/O operations. Finally, some low-level procedures are described that permit the implementation of custom ports and high-performance I/O.
4.13.1 Ports
Scheme uses ports for I/O. A "port", which can be treated like any other Scheme object, serves as a source or sink for data. A port must be open before it can be read from or written to. The standard I/O port, `console-i/o-port', is opened automatically when you start Scheme. When you use a file for input or output, you need to explicitly open and close a port to the file (with procedures described in this chapter). Additional procedures let you open ports to strings.
Many input procedures, such as `read-char' and `read', read data from the current input port by default, or from a port that you specify. The current input port is initially `console-i/o-port', but Scheme provides procedures that let you change the current input port to be a file or string.
Similarly, many output procedures, such as `write-char' and `display', write data to the current output port by default, or to a port that you specify. The current output port is initially `console-i/o-port', but Scheme provides procedures that let you change the current output port to be a file or string.
All ports read or write only ASCII characters.
4.13. INPUT AND OUTPUT 93
4.13.2 File
PortsBefore Scheme can access a file for reading or writing, it is necessary to open a port to the file. This section describes procedures used to open ports to files. Such ports are closed (like any other port) by `close-port'. File ports are automatically closed if and when they are reclaimed by the garbage collector.
Before opening a file for input or output, by whatever method, the FILENAME argument is converted to canonical form by calling the procedure `merge-pathnames' with FILENAME as its sole argument. Thus, FILENAME can be either a string or a pathname, and it is merged with the current pathname defaults to produce the pathname that is then opened.
Any file can be opened in one of two modes, "normal" or "binary". Normal mode is for accessing text files, and binary mode is for accessing other files. Some operating systems, e.g. unix, do not distinguish these modes. MS-DOS is an example of an operating system that does distinguish these modes: in normal mode, MS-DOS file ports perform "newline translation", mapping between the carriage-return/linefeed sequence that terminates text lines in files, and the `#\newline' that terminates lines in Scheme. In binary mode, MS-DOS ports do not perform newline translation. Unless otherwise mentioned, the procedures in this section open files in normal mode.
- procedure: open-input-file FILENAME
Takes a filename referring to an existing file and returns an input port capable of delivering characters from the file. If the file cannot be opened, an error of type `condition-type:file-operation-error' is signalled.
- procedure: open-output-file FILENAME [APPEND?]
Takes a filename referring to an output file to be created and returns an output port capable of writing characters to a new file by that name. If the file cannot be opened, an error of type `condition-type:file-operation-error' is signalled.
The optional argument APPEND? is an MIT Scheme extension. If APPEND? is given and not `#f', the file is opened in "append" mode. In this mode, the contents of the file are not overwritten; instead any characters written to the file are appended to the end of the existing contents. If the file does not exist, append mode creates the file and writes to it in the normal way.
- procedure+: open-i/o-file FILENAME
Takes a filename referring to an existing file and returns an I/O port capable of both reading and writing the file. If the file cannot be opened, an error of type `condition-type:file-operation-error' is signalled.
This procedure is often used to open special files. For example, under unix this procedure can be used to open terminal device files, PTY device files, and named pipes.
94 CHAPTER 4. SCHEME REFERENCE
4.13.3 Input
ProceduresThis section describes the procedures that read input. Input procedures can read either from the current input port or from a given port. Remember that to read from a file, you must first open a port to the file.
Input ports can be divided into two types, called "interactive" and "non-interactive". Interactive input ports are ports that read input from a source that is time-dependent; for example, a port that reads input from a terminal or from another program. Non-interactive input ports read input from a time-independent source, such as an ordinary file or a character string.
All optional arguments called INPUT-PORT, if not supplied, default to the current input port.
- procedure: read-char [INPUT-PORT]
Returns the next character available from INPUT-PORT, updating INPUT-PORT to point to the following character. If no more characters are available, an end-of-file object is returned.
In MIT Scheme, if INPUT-PORT is an interactive input port and no characters are immediately available, `read-char' will hang waiting for input.
- procedure: peek-char [INPUT-PORT]
Returns the next character available from INPUT-PORT, *without* updating INPUT-PORT to point to the following character. If no more characters are available, an end-of-file object is returned.(1)
In MIT Scheme, if INPUT-PORT is an interactive input port and no characters are immediately available, `peek-char' will hang waiting for input.
- procedure: char-ready? [INPUT-PORT]
Returns `#t' if a character is ready on INPUT-PORT and returns `#f' otherwise. If `char-ready?' returns `#t' then the next `read-char' operation on INPUT-PORT is guaranteed not to hang. If INPUT-PORT is a file port at end of file then `char-ready?' returns `#t'.(2)
- procedure: read [INPUT-PORT]
Converts external representations of Scheme objects into the objects themselves. `read' returns the next object parsable from INPUT-PORT, updating INPUT-PORT to point to the first character past the end of the written representation of the object. If an end of file is encountered in the input before any characters are found that can begin an object, `read' returns an end-of-file object. The INPUT-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 written representation, but the written representation is incomplete and therefore not parsable, an error is signalled.
- procedure: eof-object? OBJECT
Returns `#t' if OBJECT is an end-of-file object; otherwise returns `#f'.
- procedure+: read-char-no-hang [INPUT-PORT]
If INPUT-PORT can deliver a character without blocking, this procedure acts exactly like `read-char', immediately returning that character. Otherwise, `#f' is returned, unless INPUT-PORT is a file port at end of file, in which case an end-of-file object is returned. In no case will this procedure block waiting for input.
4.13. INPUT AND OUTPUT 95
- procedure+: read-string CHAR-SET [INPUT-PORT]
Reads characters from INPUT-PORT until it finds a terminating character that is a member of CHAR-SET (*note Character Sets::.) or encounters end of file. The port is updated to point to the terminating character, or to end of file if no terminating character was found. `read-string' returns the characters, up to but excluding the terminating character, as a newly allocated string. However, if end of file was encountered before any characters were read, `read-string' returns an end-of-file object.
On many input ports, this operation is significantly faster than the following equivalent code using `peek-char' and `read-char':
(define (read-string char-set input-port)
(let ((char (peek-char input-port)))
(if (eof-object? char)
char
(list->string
(let loop ((char char))
(if (or (eof-object? char)
(char-set-member? char-set char))
'()
(begin
(read-char input-port)
(cons char (loop (peek-char input-port))))))))))
---------- Footnotes ----------
4.13.4 Output
ProceduresOutput ports may or may not support "buffering" of output, in which output characters are collected together in a buffer and then sent to the output device all at once. (Most of the output ports implemented by the runtime system support buffering.) Sending all of the characters in the buffer to the output device is called "flushing" the buffer. In general, output procedures do not flush the buffer of an output port unless the buffer is full.
95a CHAPTER 4. SCHEME REFERENCE
However, the standard output procedures described in this section perform what is called "discretionary" flushing of the buffer. Discretionary output flushing works as follows. After a procedure performs its output (writing characters to the output buffer), it checks to see if the port implements an operation called `discretionary-output-flush'. If so, then that operation is invoked to flush the buffer. At present, only the console port defines `discretionary-output-flush'; this is used to guarantee that output to the console appears immediately after it is written, without requiring calls to `flush-output'.
All optional arguments called OUTPUT-PORT, if not supplied, default to the current output port.
- procedure+: flush-output [OUTPUT-PORT]
If OUTPUT-PORT is buffered, this causes the contents of its buffer to be written to the output device. Otherwise it has no effect. Returns an unspecified value.
- procedure: write-char CHAR [OUTPUT-PORT]
Writes CHAR (the character itself, not a written representation of the character) to OUTPUT-PORT, performs discretionary output flushing, and returns an unspecified value.
- procedure+: write-string STRING [OUTPUT-PORT]
Writes STRING to OUTPUT-PORT, performs discretionary output flushing, and returns an unspecified value. This is equivalent to writing the contents of string, one character at a time using `write-char', except that it is usually much faster.
- procedure: write OBJECT [OUTPUT-PORT]
Writes a written representation of OBJECT to OUTPUT-PORT, and returns an unspecified value. If OBJECT has a standard external representation, then the written representation generated by `write' shall be parsable by `read' into an equivalent object. Thus strings that appear in the written representation are enclosed in doublequotes, and within those strings backslash and doublequote are escaped by backslashes. `write' performs discretionary output flushing and returns an unspecified value.
- procedure: display OBJECT [OUTPUT-PORT]
Writes a representation of OBJECT to OUTPUT-PORT. Strings appear in the written representation as if written by `write-string' instead of by `write'. Character objects appear in the representation as if written by `write-char' instead of by `write'. `display' performs discretionary output flushing and returns an unspecified value.(1)
- procedure: newline [OUTPUT-PORT]
Writes an end-of-line to OUTPUT-PORT, performs discretionary output flushing, and returns an unspecified value. Equivalent to `(write-char #\newline OUTPUT-PORT)'.
- procedure+: fresh-line [OUTPUT-PORT]
Some output ports are able to tell whether or not they are at the beginning of a line of output. If OUTPUT-PORT is such a port, this procedure writes an end-of-line to the port only if the port is not already at the beginning of a line. If OUTPUT-PORT is not such a port, this procedure is identical to `newline'. In either case, `fresh-line' performs discretionary output flushing and returns an unspecified value.
4.13. INPUT AND OUTPUT 95b
- procedure+: write-line OBJECT [OUTPUT-PORT]
Like `write', except that it writes an end-of-line to OUTPUT-PORT before writing OBJECT's representation. This procedure performs discretionary output flushing and returns an unspecified value.
- procedure+: beep [OUTPUT-PORT]
Performs a "beep" operation on OUTPUT-PORT, performs discretionary output flushing, and returns an unspecified value. On the console port, this usually causes the console bell to beep, but more sophisticated interactive ports may take other actions, such as flashing the screen. On most output ports, e.g. file and string output ports, this does nothing.
- procedure+: clear [OUTPUT-PORT]
"Clears the screen" of OUTPUT-PORT, performs discretionary output flushing, and returns an unspecified value. On a terminal or window, this has a well-defined effect. On other output ports, e.g. file and string output ports, this does nothing.
- procedure+: pp OBJECT [OUTPUT-PORT [AS-CODE?]]
`pp' prints OBJECT in a visually appealing and structurally revealing manner on OUTPUT-PORT. If object is a procedure, `pp' attempts to print the source text. If the optional argument AS-CODE? is true, `pp' prints lists as Scheme code, providing appropriate indentation; by default this argument is false. `pp' performs discretionary output flushing and returns an unspecified value.
---------- Footnotes ----------
95c CHAPTER 4. SCHEME REFERENCE
4.13.5 Prompting
This section describes procedures that prompt the user for input. Why should the programmer use these procedures when it is possible to do prompting using ordinary input and output procedures? One reason is that the prompting procedures are more succinct. However, a second and better reason is that the prompting procedures can be separately customized for each user interface, providing more natural interaction. The interfaces for Edwin and for GNU Emacs have already been customized in this fashion; because Edwin and Emacs are very similar editors, their customizations provide very similar behavior.
Each of these procedure accepts an optional argument called PORT, which must be an I/O port if given. If not given, this port defaults to the value of `(interaction-i/o-port)'; this is initially the console I/O port. The required argument PROMPT must be a string.
procedure+: prompt-for-command-expression PROMPT [PORT]
Prompts the user for an expression that is to be executed as a command. This is the procedure called by the REP loop to read the user's expressions. The prompt string is formed by appending a space to PROMPT, unless PROMPT already ends in a space or is an empty string. The default behavior of this procedure is to print two newlines, the current REP loop "level number", a space, and the prompt string; flush the output buffer; then read an object and return it.
Under Edwin and Emacs, before the object is read, the interaction buffer is put into a mode that allows expressions to be edited and submitted for input using specific editor commands. The first expression that is submitted is returned as the value of this procedure.
- procedure+: prompt-for-command-char PROMPT [PORT]
Prompts the user for a single character that is to be executed as a command; the returned character is guaranteed to satisfy `char-graphic?'. If at all possible, the character is read from the user interface using a mode that reads the character as a single keystroke; in other words, it should not be necessary for the user to follow the character with a carriage return or similar rubbish.
This is the procedure called by `debug' and `where' to read the user's commands.
The prompt string is formed by appending a space to PROMPT, unless PROMPT already ends in a space or is an empty string. The default behavior of this procedure is to print two newlines, the current REP loop "level number", a space, and the prompt string; flush the output buffer; read a character in raw mode, echo that character, and return it.
Under Edwin and Emacs, instead of reading a character, the interaction buffer is put into a mode in which graphic characters submit themselves as input. After this mode change, the first such character submitted is returned as the value of this procedure.
- procedure+: prompt-for-expression PROMPT [PORT]
Prompts the user for an expression. The prompt string is formed by appending a colon and a space to PROMPT, unless PROMPT already ends in a space. The default behavior of this procedure is to print two newlines and the prompt string; flush the output buffer; then read an object and return it.
Under Edwin and Emacs, the expression is read in the minibuffer.
95d CHAPTER 4. SCHEME REFERENCE
- procedure+: prompt-for-evaluated-expression PROMPT [ENVIRONMENT [PORT]]
Prompts the user for an evaluated expression. Calls `prompt-for-expression' to read an expression, then evaluates the expression using ENVIRONMENT; if ENVIRONMENT is not given, the REP loop environment is used.
- procedure+: prompt-for-confirmation PROMPT [PORT]
Prompts the user for confirmation. The result yielded by this procedure is a boolean. The prompt string is formed by appending the string `" (y or n)? "' to PROMPT, unless PROMPT already ends in a space. The default behavior of this procedure is to print two newlines and the prompt string; flush the output buffer; then read a character in raw mode. If the character is `#\y', `#\Y', or `#\space', the procedure returns `#t'; If the character is `#\n', `#\N', or `#\rubout', the procedure returns `#f'. Otherwise the prompt is repeated.
Under Edwin or Emacs, the confirmation is read in the minibuffer.
96 CHAPTER 4. SCHEME REFERENCE
4.14 Environments and evaluation
An environment is the set of bindings for variables that is in effect at some point in a program. (See section 4.2.) Environments in Scheme are first-class objects. That is, they may be named by variables, passed as arguments to procedures, and returned as the values of procedures. Scheme includes operations for capturing the environment in effect at any point and for specifying that an expression should be evaluated relative to a particular environment.
(eval
exp env) procedureReturns the result of evaluating exp in the environment env.
(the-environment)
syntaxEvaluating the form the-environment returns the environment in which the form is evaluated.
4.15. MISCELLANEOUS 97
Note:
Scheme's static-scoping semantics imply that the-environment is not a procedure.(environment?
obj) procedureReturns #t or #f depending on whether obj is an environment.
(make-environment exp1 exp2... )
syntax
Make-environment
constructs a new environment that is contained in the environment in which this form is evaluated. The expressions exp1, exp2, ... are evaluated sequentially in this new environment, and the environment is returned. The expi are typically define expressions. A make-environment form is alternate syntax for(let () exp1 exp2, . (the-environment))
user-initial-environment
variableA variable that is initially bound to the environment in which expressions entered from the console are evaluated when Scheme is first run.
4.15 Miscellaneous
(applicable?
obj) procedureReturns #t if obj can be applied, and #f other-wise. Primitive and compound procedures are applicable.
(object-type
obj) procedureReturns the primitive datatype of the object obj, The following are the data types that would be encountered in user code:
• character
• character-string
• delayed
98 CHAPTER 4. SCHEME REFERENCE
• environment
• list
• null
• number
• primitive-procedure
• procedure
• symbol
• true
• vector
4.16 Advanced Features
(enable-language-features)
procedure(disable-language-features)
procedureThe Scheme system includes many more built-in procedures and special forms than are documented in this manual. Most of these are for system programming only. When Scheme is initially loaded, only the procedures in this manual are accessible from the initial user environment. Evaluating enable-language-features makes the additional procedures accessible.
Evaluating disable-language-features, in turn, disables these features.
Appendix A
Glossary
Buffer A buffer is a block of text that you may examine and change. Whenever you edit in Edwin, you change the contents of a buffer. To preserve a buffer for another time you will use the Chipmunk, you must save the buffer to a file on disk.
Commands A command is an instruction you give Edwin through special keys. For example, use the Find File command to copy a file from a disk into a new buffer. Edwin commands are normally used by pressing the grey function keys across the top of the Chipmunk keyboard. However, if you're used to Emacs, you may want to use control and escape sequences, instead; in Edwin, most of them work exactly as they work in Emacs. (Use the [RUN] key whenever you would normally use [ESC] )
Cursor The cursor is the blinking underline visible on the screen whenever the Chipmunk is waiting for you to type something. If you type an ordinary character (letter, number, or punctuation), it will be inserted at the current cursor position, and the cursor will move past it.
Extended Commands An extended command is a command used by name, rather than by special keys. To use an extended command, press the [EXTEND] key ( [K2] , followed by the name of the command. Your typing will appear at the bottom of the screen, in the typein window (see below). When you've typed the full name of the extended command, press [ENTER]
File A file is a block of text stored on a disk. A file may be copied from a disk into a buffer. A file is created by saving the contents of a buffer on a disk.
Kills The several most recently-deleted regions axe kept in the kill Ting. Killed text can be retrieved with a yank.
Mark The mark is an invisible point in a buffer. Many commands set it to the buffer location where they were performed. Each buffer has its own mark.
Modes Every buffer has one major mode, and maybe some minor modes. Major modes determine special Edwin behavior particular to the language you are using (e.g., Scheme or English). Minor modes add special features regardless of the language you are using in the buffer.
Point The current cursor location in each buffer is called the point. The cursor is just a reflection of the point in the current buffer.
Region Text between the point and the mark is called the region.
Saving To save is to create a disk file from a buffer. The file and the buffer are identical, but only the file remains when you logout; the buffer is erased.
Window A window is a rectangular area on the screen. Each window displays part of some buffer. Because most buffers are too big to fit in one window, only part of the buffer is visible at any time; you can see other parts by using Edwin commands to scroll through the buffer.
Bibliography
[1] Harold Abelson and Gerald Jay Sussman with Julie Sussman. Structure and Interpretation of Computer Programs. MIT Press, Cambridge, 1985.
[2] Jonathan Rees and William Clinger, editors. Revised' Report on the Algorithmic Language Scheme. Newsletter of the ACM Special Interest Group on Programming Languages, November 1986.
[3] Tod Cass. Don't Panic: A 6.001 User's guide to the Chipmunk System. January, 1984.
[4] Harold Abelson. Go Ahead - Panic: A 6.003 User's Guide to the Bobcat System. Spring Semester, 1987.
[5] Richard M. Stallman. Gnu Emacs manual. Fourth Edition, Version 17. February 1986.
103
|
'() 75 |
binding construct 61 |
|
(log 0) 87 |
binding constructs 61 |
|
* 84 |
bkpt 55 |
|
+ 84 |
bound 61 |
|
- 84 |
break 52 |
|
-1+ 85 |
break 53 |
|
/ 84 |
break-both 53 |
|
1+ 85 |
break-entry 53 |
|
< 83 |
break-exit 53 |
|
<= 84 |
breakpoint-procedure 55 |
|
= 83; 72, 73 |
caar 77 |
|
=> 71 |
cadddr 77 |
|
> 84 |
caddr 77 |
|
>= 84 |
cadr 77 |
|
abs 85 |
call 63 |
|
alphaless? 81 |
call by need 91 |
|
and 69 |
car 76; 73, 74, 75, 77, 78, 80 |
|
append 78 |
cdddar 77 |
|
applicable? 97 |
cddddr 77 |
|
apply 89 |
cdr 76; 73, 74, 75, 77, 78 |
|
ascii 82 |
ceiling 86 |
|
assoc 80; 81 |
char 82 |
|
assq 80; 81 |
character 97 |
|
assv 80; 81 |
character- string 97 |
|
atan 86; 87 |
clear-graphics 99 |
|
atom? 75 |
clear-point 99 |
|
close-channel 94 |
|
|
backup-floppy 96; 12 |
combination 63 |
|
binding 61 |
comment 59 |
|
cond 71 |
|
|
conjunction 69 |
|
|
cons 76; 74, 78, 85 |
|
|
cons-stream 91; 90 |
|
|
continuation browser 45 |
|
|
cos 86 |
|
|
debug 45 |
|
|
define 66; 97 |
first 77 |
|
delay 91; 92 |
floor 86 |
|
delayed 97 |
force 91; 92 |
|
delete-file 94 |
fourth 77 |
|
disable-language-features 98 |
gcd 86 |
|
disjunction 70 |
generate-uninterned-symbol 83 |
|
draw-line-to 99 |
|
|
draw-point 99 |
graphics 98 |
|
eighth 77 |
head 91; 90 |
|
else 71 |
identifier 59; 61 |
|
empty list 74; 68, 76, 78 |
if 70 |
|
empty stream 90 |
implode 82 |
|
empty-stream? 91 |
improper list 74 |
|
enable-language-features 98 |
initialize-floppy 96 |
|
environment 96 |
integer-divide 85 |
|
environment 98 |
integer? 83 |
|
environment browser 49 |
internal definition 67 |
|
environment? 97 |
|
|
eof 92 |
lambda 63 |
|
eq? 72; 73, 80 |
lambda expression 61 |
|
equal? 73; 72, 80 |
last 79 |
|
eqv? 72; 73, 76, 80, 81, 83 |
lazy evaluation 91 |
|
error 55 |
left 96 |
|
error-procedure 55 |
length 78 |
|
escape commands 17 |
let 64, 65 |
|
eval 96 |
list 74 |
|
even? 83 |
list 78; 88, 98 |
|
exp 86 |
list* 78 |
|
explode 82 |
list-ref 80 |
|
expt 87 |
list-tail 79 |
|
false 68 |
list? 75 |
|
#false 68 |
load-graphics 99 |
|
false 68 |
load-picture 10 |
|
f if th 77 |
log 86 |
|
file-exists? 94 |
make-environment 97 |
|
mapc 90 |
print-breadth 94 |
|
mapcar 90 |
print-depth 94 |
|
max 84 |
print-graphics-file 99 |
|
member 80; 81 |
print-picture-file 10 |
|
memq 80; 81 |
proc 90 |
|
memv 80; 81 |
procedure 98 |
|
min 84 |
procedure call 63 |
|
named let 65 |
promise 91 |
|
negative? 83 |
quote 62 |
|
newline 93 |
quotient 85; 86 |
|
nil 68 |
|
|
not 68 |
random 87 |
|
nth 80 |
read 93 |
|
nthcdr 79 |
read-from-keyboard 92 |
|
null 98 |
readch 95 |
|
null? 78 |
reductions 43 |
|
number 58, 83 |
region 61; 64, 65 |
|
number 98 |
remainder 85; 86 |
|
number? 83 |
reverse 79 |
|
right 96 |
|
|
object-type 97 |
round 86 |
|
odd? 83 |
|
|
open-printer-channel 95; 92, 94 |
second 77 |
|
open-read-channel 94 |
sequence 66 |
|
open-reader-channel 94; 92 |
set! 65 |
|
or 69 |
set-car! 77; 74 |
|
set-cdr! 77; 74, 75 |
|
|
pair 74 |
seventh 77 |
|
pair? 75 |
sin 86 |
|
peekch 95 |
sixth 77 |
|
photo 93 |
special form 59 |
|
position-pen 99 |
specialform 61 |
|
positive? 83 |
sqrt 87 |
|
primitive-procedure 98 |
store-graphics 99 |
|
prin1 93 |
store-picture 10 |
|
princ 93 |
stream 90 |
|
|
subproblems 43 |
|
symbol 98 |
where 49 |
|
symbol? 81 |
whitespace 59 |
|
t 68 |
zero? 83 |
|
tail 91; 90 |
|
|
tan 86 |
|
|
the-empty-stream 91 |
|
|
the-environment 96; 97 |
|
|
third 77 |
|
|
tofu 93 |
|
|
tokens 59 |
|
|
top level environment 61 |
|
|
trace 50 |
|
|
trace 50 |
|
|
trace-both 50 |
|
|
trace-entry 50 |
|
|
trace-exit 50 |
|
|
true 68, 70, 71 |
|
|
#true 68 |
|
|
true 68; 98 |
|
|
truncate 86 |
|
|
tyi 95 |
|
|
tyipeek 95 |
|
|
tyo 95 |
|
|
unbound 61; 62, 67 |
|
|
unbreak 53 |
|
|
untrace 50 |
|
|
user-initial-environment 97 |
|
|
variable 61; 59 |
|
|
vector 88; 98 |
|
|
vector-cons 88 |
|
|
vector-ref 89; 88 |
|
|
vector-set! 89; 88 |
|
|
vector-size 88 |
|
|
vector? 88 |