books/Seasoned Schemer

The Seasoned Schemer


Daniel Friedman and Matthias Felleisen


First (1st)

See also Scheme. This book is a sequel to The Little Schemer; The Reasoned Schemer is a paralel exploration of logical programming.

One of the things I liked about learning a programming language this way, or maybe just about scheme in general, is the seperation between the specification and implementations. Usually when I start learning a new language I try to break it as fast as possible and I am most interested in how certain little tricky bits are handled (are the file handles cross platform? does it catch infinite recursion? what kind of errors are thrown when? how big are the primitives and simple objects/user defined data types?). These are the imporant day to day issues and are a good basis for choosing a language to get work done in, but it's kind of like searching for anti-aliasing in digital photos or scanning the edges of a wall for painting mistakes. Sometimes the big picture is the whole point and it's worth putting up with small flaws.


The Y combinator function is never defined in this book, I had to copy it out of The Little Schemer:

(define Y
  (lambda (thing)
    ((lambda (le)
       ((lambda (f) (f f))
        (lambda (f) (le (lambda (x) ((f f) x))))))

Also eqlist?:

(define eqlist?
  (lambda (a b)
     ((and (null? a) (null? b)) #t)
     ((or (null? a) (null? b)) #f)
     ((and (atom? (car a)) (atom? (car b)))
       (and (eqlist? (cdr a) (cdr b))))
     ((or (atom? (car a)) (atom? (car b))) #f)
     (else (and (eqlist? (car a) (car b)) (eqlist? (cdr a) (cdr b)))))))

MIT/GNU Scheme doesn't seem to have letcc or try; I stuck with call-with-current-continuation:

(call-with-current-continuation (lambda (hook) ...)
; is the same as
(letcc hook (...))

; as noted in the book (p. 89)
(try x a b)
; is the same as
(letcc success 
  (letcc x 
    (success a)) 
; is the same as
  (lambda (success)
        (lambda (x)
          (success a)))

When reimplementing scheme at the end of the book, I'm kind of miffed that the (letcc ...) definition basically just uses letcc, because magic North Pole compasses seem like the most interesting part.


Y-bang is the "applicative-order imperative Y combinator":

(define Y-bang
  (lambda (f)
    ((h (f (lambda (arg) (h arg)))))

At one point I wondered:

Is there any language/interpreter which, when it runs into an undefined
value, lets you define it on the spot? Would be great for learners.

MIT/GNU Scheme, of course, has this feature in the error REPL. But I never noticed it.

The Next 10 Commandments

The Eleventh Commandment

Use additional arguments when a function needs to know what other arguments to the function have been like so far.

The Twelfth Commandment

Use (letrec ..) to remove arguments that do not change for recursive applications.

The Thirteenth Commandment

Use (letrec ...) to hide and protect functions.

The Fifteenth Commandment

Use (let ...) to name the values of repeated expressions in a function definition if they may be evaluated twice for one and same use of the function. And use (let ...) to name the values of expressions (without set!) that are re-evaluated every time a function is used.

The Sixteenth Commandment

Use (set! ...) only with names define in (let ...)s

The Seventeenth Commandment

Use (set! x ...) for (let ((x ..)) ..)) only if there is at least one (lambda .. between it and the (let ..), or if the new value for x is a function that refers to x.

The Eighteenth Commandment

Use (set! x ...) only when the value that x refers to is no longer needed.

The Nineteenth Commandment

Use (set! ...) to remember valuable things between two distinct uses of a function.

The Twentieth Commandment

When thinking about a value created with (letcc ...), write down the function that is equivalent but does not forget. Then, when you use it, remember to forget.

I love that last sentence!