C311 Scheme Extensions
Descriptions of the extensions of standard Scheme used in this course but not
described in EOPL follow. Some of these extensions are provided
by Chez Scheme, and others by loading an indicated file. Transcripts
beginning with > illustrate these extensions.
Contents
- Gensym
- Printf
- Error
- Form-case
- Scheme++
The procedure gensym, provided by Chez Scheme, returns returns a
fresh symbol (a newly generated symbol) when called with
no arguments. In Chez Scheme, gensyms (symbols returned by
gensym) print as #:g followed by a natural number, as
indicated in the example above. In EOPL they print as
g followed by a natural number.
> (gensym)
#:g0
The procedure printf, provided by Chez Scheme, is patterned
loosely after the C++ procedure of the same name. It takes a format string
followed optionally by other arguments. The characters of the format
string are printed in order from left to right until the end of the string
is reached, except that if during this process one of the two character
sequences that follow is encountered, instead of printing the two
characters the specified action is taken.
- ~s
- print the value of the next argument using the procedure write
- ~a
- print the value of the next argument using the procedure display
- ~c
- print the value of the next argument using the procedure
write-char
- ~%
- print a newline
- ~~
- print a single tilde character
> (printf "The ~s procedure is very ~a.~%" "printf" "handy")
The "printf" procedure is very handy.
> (printf "~~dum, ~cdee~%" #\~)
~dum, ~dee
The procedure error, provided by Chez Scheme, takes a
symbol, S, followed by a format string and optionally other
arguments. It prints a newline, followed by "Error in S:
text", where text is the result of invoking
printf with the format string and following arguments, followed
by another newline, and resets Scheme. When Scheme is reset, control is
returned to the waiter (read-evaluate-print loop) and a new top-level
prompt is printed.
> (begin (display 'before) (error 'testing "one, ~s" 'two) (display after))
before
Error in testing: one, two
>
Observe that after was never displayed.
By convension the symbol passed as the first argument to error
names the procedure that calls it. EOPL uses a version of the
procedure error that is somewhat different.
The form form-case simplifies the parsing of languages that have
a Scheme-like syntax. It is an extension of Chez Scheme obtained by
loading form-case.ss.
The syntax of a form-case expression is
(form-case expression clause ...)
Each clause must be of one of the forms listed below. Each clause is
listed with a corresponding condition, an arrow "==>", and
then the effect of the clause if it is "taken". No two clauses of a
form-case expression may have the same condition. The expression
is evaluated first; call its value V. If a clause has a condition
that is satisfied by V, then the clause is taken with its
corresponding effect; otherwise, an error is raised.
- (variable var expression ...)
- V is a symbol ==> evaluate (begin
expression ...) with var bound to V.
- (constant var expression ...)
- V is a constant (number, boolean, character, or string)
==> evaluate (begin
expression ...) with var bound to V.
- (keyword fields expression ...)
-
V is a pair, the car of V is the same symbol as
keyword, and fields matches the structure of the cdr of
V==> apply (lambda fields expression
...) to the cdr of V.
- (call fields expression ...)
- V is a pair and car of V is not a symbol used as a
keyword in another clause==> apply (lambda
fields expression ...) to V.
- (else expression ...)
- Evaluate (begin expression ...).
For example, form-case is used below to define a predicate takes a variable
and a lambda-calculus expression (represented in Scheme syntax) and
indicates whether the variable occurs free in the expression.
> (load "form-case.so")
> (define free?
(lambda (var exp)
(form-case exp
(variable v (eq? v var))
(lambda (formals body)
(and (not (eq? var (car formals)))
(free? var body)))
(call (rator rand)
(or (free? var rator)
(free? var rands))))))
> (free? 'a '(lambda (a) (a b)))
#f
> (free? 'b '(lambda (a) (a b)))
#t
chaynes@indiana.edu