1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
============================
The Seasoned Schemer
============================
:by: Daniel Friedman and Matthias Felleisen
:Edition: First (1st)
See also `Scheme </k/software/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 Little Schemer: /k/books/littleschemer/
Issues/Omissions
--------------------------
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))))))
thing)))
Also ``eqlist?``::
(define eqlist?
(lambda (a b)
(cond
((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))
b)
; is the same as
(call-with-current-continuation
(lambda (success)
(begin
(call-with-current-continuation
(lambda (x)
(success a)))
b)))
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.
Notes
-----------------
Y-bang is the "applicative-order imperative Y combinator"::
(define Y-bang
(lambda (f)
(letrec
((h (f (lambda (arg) (h arg)))))
h)))
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!**
|