The book
Friedman, Daniel P. and Felleisen, Matthias and Bibby, Duane, 1996. The Seasoned Schemer. 2nd edition, The MIT Press,Abstract: The notion that "thinking about computing is one of the most exciting things the human mind can do" sets both The Little Schemer (formerly known as The Little LISPer) and its new companion volume, The Seasoned Schemer, apart from other books on LISP. The authors' enthusiasm for their subject is compelling as they present abstract concepts in a humorous and easy-to-grasp fashion. Together, these books will open new doors of thought to anyone who wants to find out what computing is really about. The Little Schemer introduces computing as an extension of arithmetic and algebra; things that everyone studies in grade school and high school. It introduces programs as recursive functions and briefly discusses the limits of what computers can do. The authors use the programming language Scheme, and interesting foods to illustrate these abstract ideas. The Seasoned Schemer informs the reader about additional dimensions of computing: functions as values, change of state, and exceptional cases. The Little LISPer has been a popular introduction to LISP for many years. It had appeared in French and Japanese. The Little Schemer and The Seasoned Schemer are worthy successors and will prove equally popular as textbooks for Scheme courses as well as companion texts for any complete introductory course in Computer Science.
Some interesting material can be found in prof Lance R. Williams’ course page.
Call with current continuation: the letcc macro
The fundamental macro letcc in the form
(letcc k body ...)
k to the current continuation Continuations by example in body... expressions; for the sake of clarity, it expands to(call-with-current-continuation (λ (k) body ...))
call/cc, which leaves and enters again the dynamic-wind frames, hence the parameterize forms, between the capture and the resume. It used to be built on continuation-capture and continuation-graft of Module (chicken continuation), after A Better API for First-Class Continuations by Marc Feeley, but a graft does not unwind nor rewind those frames: a continuation resumed across a parameterize left the runtime's winds stale, and a second resume crashed it.Implementation
(module
(aux continuation)
*
(import scheme (chicken base) (aux base))
(define-syntax-rule
(letcc/call hop body ...)
(call-with-current-continuation (λ (hop) body ...)))
(define-syntax-rule (letcc hop body ...) (letcc/call hop body ...))
(define (callcc f) (letcc k (f k)))
(define-syntax-rule
(letcc* next ((v exp) ...) body ...)
(letcc success
(let* ((v (letcc next (success exp))) ... (next success))
body
...)))
(define-syntax-rule
(literal else)
(trycc (next exp ...) (else body ...))
(letcc* hop ((v (let1 (next (τ (hop (void)))) exp)) ...) body ...)))
test/letcc/multiarg: pass
(define (test/letcc/multiarg _) (⊦= 'a (letcc k (k 'a))))
((eta 0.0) (memory #(6291456 2054040 1048576)) (stdout "") (stderr ""))
test/letcc*: pass
The frame in The Seasoned Schemer: page 89, see rember1* definition. is of inspiration of the letcc* macro.
(call-with-current-continuation
(λ (success) (let* ((v (letcc ⤶ (success vexpr))) (⤶ success)) body ...)))
(define (test/letcc* _)
(⊦= '(1) (letcc* ⤶ ((v (cons 1 '())) (w (cons 2 v))) (cons 4 w)))
(⊦= '(2 1) (letcc* ⤶ ((v (cons 1 (⤶ '(1)))) (w (cons 2 v))) (cons 4 w)))
(⊦= '(4 3 1)
(letcc*
⤶
((v (cons 1 (⤶ '(1)))) (w (cons 2 (⤶ (cons 3 v)))))
(cons 4 w)))
(⊦= '(1 2) (letcc* ⤶ ((v (cons 3 (⤶ '(2))))) (cons 1 v)))
(⊦= '(3 2) (letcc* ⤶ ((v (cons 1 (⤶ '(2))))) (⤶ (cons 3 v))))
(⊦= '(2) (letcc* ⤶ ((v (cons 3 (⤶ '(2))))) (cons 1 (⤶ v))))
(⊦= '(4 2) (letcc* ⤶ ((v (cons 3 (⤶ '(2))))) (cons 1 (⤶ (cons 4 v))))))
((eta 0.0) (memory #(6291456 2050176 1048576)) (stdout "") (stderr ""))
test/trycc: pass
(define (test/trycc _)
(⊦= 5 (trycc (✗ (+ 1 (✗)) (+ 2 3)) (else (cons 3 '()))))
(⊦= 3 (trycc (✗ (+ 1 2) (+ 2 (✗))) (else (cons 3 '()))))
(⊦= '(3) (trycc (✗ (+ 1 (✗)) (+ 2 (✗))) (else (cons 3 '())))))
((eta 0.0) (memory #(6291456 2054456 1048576)) (stdout "") (stderr ""))
test/letcc/dfs: pass
(define (test/letcc/dfs _)
(define t1 '(a (b (d h)) (c e (f i) g)))
(define t2 '(1 (2 (3 6 7) 4 5)))
(letrec ((*saved* '())
(col '())
(witness (gensym))
(dft-node
(lambda (tree)
(cond ((null? tree) (restart))
((not (pair? tree)) tree)
(else
(letcc cc
(push! (τ (cc (dft-node (cdr tree)))) *saved*)
(dft-node (car tree)))))))
(restart
(τ (if (null? *saved*)
witness
(let1 (cont (pop! *saved*)) (cont)))))
(dft-comb
(lambda (another)
(lambda (tree)
(let1 (node1 (dft-node tree))
(if (eq? node1 witness)
witness
(list node1 (dft-node another)))))))
(dft2 (lambda (v)
(if (eq? v witness)
(reverse col)
(begin (push! v col) (restart))))))
(⊦= '(a b d h c e f i g) (dft2 (dft-node t1)))
(set! col '())
(⊦= '((a 1)
(a 2)
(a 3)
(a 6)
(a 7)
(a 4)
(a 5)
(b 1)
(b 2)
(b 3)
(b 6)
(b 7)
(b 4)
(b 5)
(d 1)
(d 2)
(d 3)
(d 6)
(d 7)
(d 4)
(d 5)
(h 1)
(h 2)
(h 3)
(h 6)
(h 7)
(h 4)
(h 5)
(c 1)
(c 2)
(c 3)
(c 6)
(c 7)
(c 4)
(c 5)
(e 1)
(e 2)
(e 3)
(e 6)
(e 7)
(e 4)
(e 5)
(f 1)
(f 2)
(f 3)
(f 6)
(f 7)
(f 4)
(f 5)
(i 1)
(i 2)
(i 3)
(i 6)
(i 7)
(i 4)
(i 5)
(g 1)
(g 2)
(g 3)
(g 6)
(g 7)
(g 4)
(g 5))
(dft2 ((dft-comb t2) t1)))))
((eta 0.001) (memory #(6291456 2067520 1048576)) (stdout "") (stderr ""))