The Seasoned Schemer

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 ...)
binds 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 ...))
that is, to plain 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 ""))
Categories: scheme  books 
Tags: callcc 

See also

Final shift for call/cc Direct implementation of shift and reset Call with Current Continuation Patterns The Little Schemer Cogen in six lines Representing monads The (aux anthropic) module The Anthropic Messages API, offline The (aux cml) module Events, threads, synchronous variables, the library and I/O The (aux hakaru10) modules Random sources, distributions, the language, exact inference and examples The (aux kanren) modules Arithmetic, dates, presentation of answers and a union-find miniKanren The (aux games dice-of-doom) module Dice of Doom The (aux machine) modules Environments, the SC machine and the SECD machine The (aux schemer seasoned) module The Seasoned Schemer The (aux continuation) modules Classic operators, escapers, amb and Collatz sequences The (aux category) modules Monads: list, maybe, probability, ziplist, difference lists and state The (aux timsort) module Sorting and the trace buffer The (aux fds) modules Functional queues and union-find The (aux sxml) module Rendering SXML to HTML The (aux variable) module Logic variables introduced by fresh The (aux tabling) module Memoization and tabled definitions The (aux commons) module Learning tests for CHICKEN Scheme Promises delay and make-promise The Ackermann function On unary numbers, as lists Concurrent ML for CHICKEN Scheme Porting SML/NJ CML as the (aux cml) library CHICKEN Scheme Versions and implementation notes The SBRAL data structure Skew Binary Random-Access Lists Pattern matching Scheme macrology: a generalized pattern matcher The (aux hansei) modules Inference, random sources, lazy lists, logic programming and example models The (aux nondeterministic) module Learning tests for Scheme The (aux stream) modules Streams, streams after SICP, and sequences and power series The (aux unittest) module Bootstrapping a unittest framework TAOCP: Volume 4, Fascicle 6. Satisfiability Scheme lang: Chez, 48 and Chicken Some docs, refs and containers, respectively. The Reasoned Schemer miniKanren, microKanren and some implementations Aggregation predicates for µkanren Groups, window functions, sets and enumerations miniKanren, live and untagged Quine generation via relational interpreters Pure, declarative, and constructive arithmetic relations A declarative pearl Adding generic functions to Scheme Handling control
Table of Contents