Previous: scheme expansion, Up: scheme [Index]
This appendix contains sample definitions for some of the keywords described in this report in terms of simpler forms:
cond
The cond
keyword could be defined in terms of if
,
let
and begin
using syntax-rules
as follows:
(define-syntax cond (syntax-rules (else =>) ((cond (else result1 result2 ...)) (begin result1 result2 ...)) ((cond (test => result)) (let ((temp test)) (if temp (result temp)))) ((cond (test => result) clause1 clause2 ...) (let ((temp test)) (if temp (result temp) (cond clause1 clause2 ...)))) ((cond (test)) test) ((cond (test) clause1 clause2 ...) (let ((temp test)) (if temp temp (cond clause1 clause2 ...)))) ((cond (test result1 result2 ...)) (if test (begin result1 result2 ...))) ((cond (test result1 result2 ...) clause1 clause2 ...) (if test (begin result1 result2 ...) (cond clause1 clause2 ...)))))
case
The case
keyword could be defined in terms of let
,
cond
, and memv
using syntax-rules
as follows:
(define-syntax case (syntax-rules (else) ((case expr0 ((key ...) res1 res2 ...) ... (else else-res1 else-res2 ...)) (let ((tmp expr0)) (cond ((memv tmp '(key ...)) res1 res2 ...) ... (else else-res1 else-res2 ...)))) ((case expr0 ((keya ...) res1a res2a ...) ((keyb ...) res1b res2b ...) ...) (let ((tmp expr0)) (cond ((memv tmp '(keya ...)) res1a res2a ...) ((memv tmp '(keyb ...)) res1b res2b ...) ...)))))
let*
The let*
keyword could be defined in terms of let
using
syntax-rules
as follows:
(define-syntax let* (syntax-rules () ((let* () body1 body2 ...) (let () body1 body2 ...)) ((let* ((name1 expr1) (name2 expr2) ...) body1 body2 ...) (let ((name1 expr1)) (let* ((name2 expr2) ...) body1 body2 ...)))))
letrec
The letrec
keyword could be defined approximately in terms of
let
and set!
using syntax-rules
, using a helper to
generate the temporary variables needed to hold the values before the
assignments are made, as follows:
(define-syntax letrec (syntax-rules () ((letrec () body1 body2 ...) (let () body1 body2 ...)) ((letrec ((var init) ...) body1 body2 ...) (letrec-helper (var ...) () ((var init) ...) body1 body2 ...)))) (define-syntax letrec-helper (syntax-rules () ((letrec-helper () (temp ...) ((var init) ...) body1 body2 ...) (let ((var <undefined>) ...) (let ((temp init) ...) (set! var temp) ...) (let () body1 body2 ...))) ((letrec-helper (x y ...) (temp ...) ((var init) ...) body1 body2 ...) (letrec-helper (y ...) (newtemp temp ...) ((var init) ...) body1 body2 ...))))
The syntax <undefined>
represents an expression that returns
something that, when stored in a location, causes an exception with
condition type &assertion
to be raised if an attempt to read from
or write to the location occurs before the assignments generated by the
letrec
transformation take place. (No such expression is defined
in Scheme.)
letrec*
The letrec*
keyword could be defined approximately in terms of
let
and set!
using syntax-rules
as follows:
(define-syntax letrec* (syntax-rules () ((letrec* ((var1 init1) ...) body1 body2 ...) (let ((var1 <undefined>) ...) (set! var1 init1) ... (let () body1 body2 ...)))))
The syntax <undefined>
is as in the definition of letrec
above.
let-values
The following definition of let-values
using syntax-rules
employs a pair of helpers to create temporary names for the formals.
(define-syntax let-values (syntax-rules () ((let-values (binding ...) body1 body2 ...) (let-values-helper1 () (binding ...) body1 body2 ...)))) (define-syntax let-values-helper1 ;; map over the bindings (syntax-rules () ((let-values ((id temp) ...) () body1 body2 ...) (let ((id temp) ...) body1 body2 ...)) ((let-values assocs ((formals1 expr1) (formals2 expr2) ...) body1 body2 ...) (let-values-helper2 formals1 () expr1 assocs ((formals2 expr2) ...) body1 body2 ...)))) (define-syntax let-values-helper2 ;; create temporaries for the formals (syntax-rules () ((let-values-helper2 () temp-formals expr1 assocs bindings body1 body2 ...) (call-with-values (lambda () expr1) (lambda temp-formals (let-values-helper1 assocs bindings body1 body2 ...)))) ((let-values-helper2 (first . rest) (temp ...) expr1 (assoc ...) bindings body1 body2 ...) (let-values-helper2 rest (temp ... newtemp) expr1 (assoc ... (first newtemp)) bindings body1 body2 ...)) ((let-values-helper2 rest-formal (temp ...) expr1 (assoc ...) bindings body1 body2 ...) (call-with-values (lambda () expr1) (lambda (temp ... . newtemp) (let-values-helper1 (assoc ... (rest-formal newtemp)) bindings body1 body2 ...))))))
let*-values
The following macro defines let*-values
in terms of let
and let-values
using syntax-rules
:
(define-syntax let*-values (syntax-rules () ((let*-values () body1 body2 ...) (let () body1 body2 ...)) ((let*-values (binding1 binding2 ...) body1 body2 ...) (let-values (binding1) (let*-values (binding2 ...) body1 body2 ...)))))
let
The let
keyword could be defined in terms of lambda
and
letrec
using syntax-rules
as follows:
(define-syntax let
(syntax-rules ()
((let ((name val) ...) body1 body2 ...)
((lambda (name ...) body1 body2 ...)
val ...))
((let tag ((name val) ...) body1 body2 ...)
((letrec ((tag (lambda (name ...)
body1 body2 ...)))
tag)
val ...))))
Previous: scheme expansion, Up: scheme [Index]