sicp刚进大学的时候看过三章, 现在基本上忘光了. 只能从头看, 希望这次能看完.
我用的scheme环境是drscheme, 功能十分好. scheme是一门很简单的函数式语言, 看一遍它的R5RS标准基本上就可以用了.
full text version http://mitpress.mit.edu/sicp
The acts of the mind, wherein it exerts its power over simple ideas, are chiefly these three: 1. Combining several simple ideas into one compound one, and thus all complex ideas are made. 2. The second is bringing two ideas, whether simple or complex, together, and setting them by one another so as to take a view of them at once, without uniting them into one, by which it gets all its ideas of relations. 3. The third is separating them from all other ideas that accompany them in their real existence: this is called abstraction, and thus all its general ideas are made.
John Locke, An Essay Concerning Human Understanding (1690)
前缀表示法(prefix notation)的两个优点:
1. 可以适应带有任意多个参数的过程.
2. 允许组合式层层嵌套, 即组合式本身可以作为别的组合式的基本元素. e.g
(+ (* 3 5)(- 10 6)).
Lisp obeys the convention that every expression has a value. This convention, together with the old reputation of Lisp as an inefficient language, is the source of the quip by Alan Perlis (paraphrasing Oscar Wilde) that ``Lisp programmers know the value of everything but the cost of nothing.''
通过使用(define varible value)语法定义变量的行为, 使得解释器必须具备一种保持 变量名---值 匹配对的存储能力. 也就是解释器要维护一张表, 来查询 变量名---值的对映关系. 这被称作Global Environment, Environment是具有普遍性的概念, 它为求值过程提供上下文.
组合式(Combination)
e.g
(+ (+ 2 (* 4 6))
(+ 3 5 7))
的计算过程
In fact, the "percolate values upward" form of the evaluation rule is an example of a general kind of process known as tree accumulation. 这种一般性求值规则还有两种意外情况, 一种就是define操作, 它具有自己的求值规则.
针对特殊语法规则的脚注:
Special syntactic forms that are simply convenient alternative surface structures for things that can be written in more uniform ways are sometimes called syntactic sugar, to use a phrase coined by Peter Landin. In comparison with users of other languages, Lisp programmers, as a rule, are less concerned with matters of syntax. (By contrast, examine any Pascal manual and notice how much of it is devoted to descriptions of syntax.) This disdain for syntax is due partly to the flexibility of Lisp, which makes it easy to change surface syntax, and partly to the observation that many ``convenient'' syntactic constructs, which make the language less uniform, end up causing more trouble than they are worth when programs become large and complex. In the words of Alan Perlis, ``Syntactic sugar causes cancer of the semicolon.''
定义过程的一般形式:
(define (<name> <formal parameter>) <body))
求值的两种顺序: 正则序(normal order)和应用序(applicative order)
正则序: 完全展开然后归约. 应用序: 先求值参数然后应用.
通过cond表达式和if表达式实现的abs函数.
;; (cond (<p1> <e1>)
;; (<pn> <en>)
;; (else <ee>))
(define (abs1 x)
(cond ((< x 0) (- 0 x))
(else x)))
;; (if <predicate> <consequent> <alternative>)
(define (abs2 x)
(if (< x 0) (- 0 x) (x)))
谓词: <, =, >, (and <e1>...<en>), (or <e1>...<en>), (not <e>)
ex1.3 Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.
(define (sum a b c)
(if (> (+ b c) (if (> (+ a b)
(+ a c))
(+ a b)
(+ a c)))
(+ b c) (if (> (+ a b)
(+ a c))
(+ a b)
(+ a c))))
--------------------------
(define (sum a b c)
(define x (if (> (+ a b)
(+ a c))
(+ a b)
(+ a c)))
(if (> (+ b c) x)
(+ b c) x))
lisp/scheme一个十分好的特性是符号谓词过程都可以以一个基本元素的形式充当参数或者是返回值. e.g
(define (a-plus-abs-b a b)
((if (> b 0) + -) a b))
ex1.5 Ben Bitdiddle has invented a test to determine whether the interpreter he is faced with is using applicative-order evaluation or normal-order evaluation. He defines the following two procedures:
(define (p) (p))
(define (test x y)
(if (= x 0)
0
y))
Then he evaluates the expression
(test 0 (p))
What behavior will Ben observe with an interpreter that uses applicative-order evaluation? What behavior will he observe with an interpreter that uses normal-order evaluation? Explain your answer. (Assume that the evaluation rule for the special form if is the same whether the interpreter is using normal or applicative order: The predicate expression is evaluated first, and the result determines whether to evaluate the consequent or the alternative expression.)
用两种规则进行代换:
正则序求值时, 将参数完全展开然后归约. 所以(test 0 (p))展开为:
(if (= 0 0)
0
(p))
应用序求值时, 先对参数进行求值, 然后归约, 所以(test 0 (p))对参数(p)求值, 陷入死循环中.
DrScheme采用的是应用序规则. 所以运行这段程序没有响应.
ex1.6
Alyssa P. Hacker doesn't see why if needs to be provided as a special form. ``Why can't I just define it as an ordinary procedure in terms of cond?'' she asks. Alyssa's friend Eva Lu Ator claims this can indeed be done, and she defines a new version of if:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Eva demonstrates the program for Alyssa:
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
Delighted, Alyssa uses new-if to rewrite the square-root program:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x))) (c1)
What happens when Alyssa attempts to use this to compute square roots? Explain.
这样做是很危险的, 因为换置if的new-if是一个过程, 那么若它的参数求值规则是应用序的话, 上面代码c1处的sqrt-iter在判断条件是否满足前就已经开始计算. 所以最后的结果是错的.