Page Numbers: Yes X: 306 Y: 1.0" First Page: 1
Margins: Top: 1.0" Bottom: 1.3"
Heading:
SCHEME vs. 3-LISP LISP: LANGUAGE AND LITERATURE May 3, 1984
————————————————————————————————————————————
SCHEME vs. 3-LISP: An Informal Comparison
Filed as:[phylum]<3-lisp>course>notes>Scheme-3-Lisp.bravo
User.cm:
[phylum]<BrianSmith>system>user.classic
Last edited:
May 3, 1984 9:31 AM
————————————————————————————————————————————
The following is an informal comparison of the syntax of Scheme and 3-LISP to allow transformation of simple Scheme programs into (roughly) equivalent 3-LISP programs. Because of the substantial foundational differences between Scheme and 3-LISP (most notably the distinction between Scheme as an evaluating language and 3-LISP as a normalizing language) such syntactic transformations cannot capture many of the differences between the dialects. Nonetheless, these guidelines should be an aid for translating the simpler sample programs from the first few chapters of Abelson and Sussman.
"Special Forms"
For each of the special forms of Scheme there is usually a corresponding special procedure in 3-LISP that provides much the same functionality but with slightly different syntax (the converse isn’t nearly so true). In particular, for reasons discussed later, Scheme tends to use parentheses where 3-LISP uses square brackets. The differing special forms include (italics are used to signify meta-theoretic variables):
Scheme:3-LISP:
LET:(let ((v1 e1)(let [[v1 e1]
(
v2 e2) [v2 e2]
... ...
(
vn en)) [vn en]]
body) body)
Scheme:3-LISP:
DEFINE:(define (func-name arg1 ... argn)(define func-name
body) (lambda [arg1 ... argn]
body))
Note that both Scheme and 3-LISP allow several body expressions, though 3-LISP uses this capability rarely. Thus, while Scheme definitions making use of this feature can be translated directly using (lambda[arg1 ... argn]body1 ... bodyn), it is considered better programming practice to use (lambda[arg1 ... argn](beginbody1 ... bodyn)). Letrec is not used in Scheme; see the section on internal definitions below.
Scheme:3-LISP:
COND:(cond (b1 e1)(cond [b1 e1]
(
b2 e2) [b2 e2]
... ...
(
bn en) [bn en]
(else
eelse)) [$true eelse])
Internal Definitions
In 3-LISP, the LET or LETREC special form is used for definitions of functions internal to a procedure. Scheme typically makes use of internal DEFINEs. Thus (from Abelson and Sussman, p. 32):
Scheme:3-LISP:
(define (factorial n)(define factorial
(define (iter product counter)
(lambda [n]
(if (> counter n)
(letrec [[iter (lambda [product counter]
product
(if (> counter n)
(iter (* counter product)
product
(+ counter 1))))
(iter (* counter product)
(iter 1 1))
(+ counter 1))))]]
(iter 1 1))))
Quoting, Lists, and Rails
Scheme uses the same (internal) structure for what in 3-LISP would be the separate structure types PAIR and RAIL. In other words, Scheme uses parenthesized expressions to signify both function application and enumeration (sequences). Thus in some Scheme contexts the expression (A1A2A3) will signify the application of the function signified by A1 to the arguments signified by A2 and A3, whereas in other contexts in will signify the list (sequence) of the three objects signified by A1, A2, and A3, respectively. In a Scheme context where parentheses would be taken to signify function application, the procedure LIST can be used, which simply returns a list of its arguments: thus (LIST123) will evaluate to (123).
It follows that programs that are intended to operate on lists as data in Scheme should operate on rails in 3-LISP. The correspondence between the appropriate functions are as follows:
Scheme:3-LISP:
carfirst
cdrrest
conscons
listlist (or simply [ ... ])
nullnull
nil[] or $false (see below)
Notes:
3-LISP’s list is rarely used since the effect of (liste1 ... en) can be achieved with the simpler [e1 ... en]. Also, NIL in Scheme is used both for the empty list and the boolean value denoting falsity. Depending on the intended meaning, the appropriate 3-LISP translation will be [] or $false respectively.
Finally, if the arguments to a Scheme list would evaluate to themselves (numerals, for example), a simple quote can be used in place of LIST (since in Scheme ’(123) will evaluate to (123)). Therefore, arguments to Scheme procedures that take lists as data are often given as, e.g., ’(1 2 3). In 3-LISP, the corresponding expression would simply be the rail [1 2 3]; the extra quote mark in Scheme is a consequence of its being an evaluating, rather than normalizing, language.
For example, consider the Scheme program to reverse a list, viz.:
(define (reverse l); This is SCHEME
(cond ((null l) nil)
(else (append (reverse (cdr l))
(list (car l))))))
which would be invoked by
1> (reverse ’(1 2 3 (4 5))); This is SCHEME
1= ((4 5) 3 2 1)
The corresponding 3-LISP definition is
(define reverse; This is 3-LISP
(lambda [l]
(cond [(null l) []]
[$true (append (reverse (rest l))
[(first l)])])))
invoked by
1> (reverse [1 2 3 [4 5]]); This is 3-LISP
1= [[4 5] 3 2 1]
(See the 3-LISP primer, p. 7, for a definition of append in 3-LISP.)
These translation guidelines should allow generating appropriate 3-LISP for simple Scheme programs. For programs for which these guidelines are insufficient, deeper differences between the languages are probably involved, and no purely syntactic translation will be possible; the intent of the program will have to be considered.