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

  1. Gensym
  2. Printf
  3. Error
  4. Form-case
  5. Scheme++

Gensym

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

Printf

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

Error

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.

Form-case

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