May 18, 2004 10:07 PM
Scheme is a dialect of lisp. Guile is Project GNU's library that
contains an interpreter for Scheme. Since I am much more familiar with
lisp, the notes below highlight the main differences between the two.
First of all, defun
is define
and the function name appears inside
the parenthesis where in Lisp only the parameters reside.
(define (dist x y) (sqrt (+ (* x x) (* y y))))
setq
is set!
. The 'p' part of all predicates are '?' in
Scheme. That is, nullp
becomes null?
. Instead of &rest
, a
dot is used after which any number of parameters might appear. Like
defun
, defmacro
becomes define-macro
.
Scheme supports lexical scope which when combined with internal definitions is very useful. The Scheme standard also requires every conforming implementation to employ recursive tail call elimination.
Each procedure can be told explicitly what to do with its result when
composition of procedures might occur by Continuation Passing Style
(CPS). CPS puts the burden of establishing and administering
continuations on the programmer. Implicit continuations can be
accessed in Scheme by using call/cc
primitive which stands for
call-with-current-continuation. This primitive takes one argument, a
procedure that itself takes one argument. Scheme calls that argument
procedure with the continuation of the call/cc
as the argument.
Continuations can be used to perform a nonlocal exit similar to setjmp
and longjmp procedures in C or catch and throw procedures in versions
of Lisp. A continuation provided is valid forever. Even a
multi-threaded system can be implemented by using a continuation to
remember the status of each thread that isn't running right
now. Here's an example to demonstrate call/cc
:
(define (list-mult numlist) (call/cc (lambda (escape) (define (helper numlist) (if (null? numlist) 1 (if (= (car numlist) 0) (escape 0) (* (car numlist) (helper (cdr numlist)))))) (helper numlist))))
The list-mult
procedure defined above multiplies the elements of
numlist
only if there are no zeroes in it. A call/cc
is wrapped
around a conventional helper procedure that does not use continuations
and the resulting continuation is invoked if a 0 is encountered. No
multiplication takes place until the recursion reaches the end of the
list. They are done on the way out. Invoking the escape continuation
within helper
avoids all of the multiplications.