作者descent (「雄辩是银,沉默是金」)
看板PLT
标题Fw: [心得] sicp 简体中文版本
时间Tue Jun 2 20:11:42 2015
※ [本文转录自 CompBook 看板 #1KX6S-Mb ]
作者: descent (「雄辩是银,沉默是金」) 看板: CompBook
标题: [心得] sicp
时间: Sun Dec 7 22:41:48 2014
全名是: Structure and Interpretation of Computer Programs
中文名称: 算机程序的构造和解
20131024 淘宝订单 20131104 到手, 12 天才收到, 有点久。
费用 42 * 5.1 = 214.2 + 145 = 359.2 委托代买购得。
电子版本 (
http://goo.gl/QwRmW ), 当然是英文的, 要不然我就不用花钱买中文的版本
。
简体中文版本看来薄薄的, 可别以为是本小书, 整整有 472 页, 所以纸质真的不怎麽样
(薄的厉害, 我觉得用印表机得到的品质都比这本书好), 在上头写注记得小心点, 一不小
心可能就划破纸张。在阅读上也有点困扰, 整本书歪斜的很厉害, 不好拿着看。
简体中文版本出版日期: 2004 年 2 月 1 日, 我这本是 201306 第八刷, 原文书 1984
年出版,是美麻省理工院 (MIT) 多年使用的一本教材, 1996 年修第二版。
後来 MIT 始用 python 教授此,代替了原本的 Scheme: Why MIT switched from
Scheme to Python (
http://goo.gl/yd2l )
淘宝有些书是影印的版本, 还好这本不是, 我本来还担心这本已经出版了这麽久的一段时
间, 会买不到正版的, 不过看来这本书还有陆续再出版。
我的进度很缓慢, 不过我很有耐心和毅力, 忍住开发 os, qt for android, uefi 程式的
相关诱惑, 专心看这本书, 慢慢地, 慢慢地, 我越来越可以看下去了, 速度也提升了一点
点。她有什麽魔力让我愿意这样做呢? ref 2 提到: 您法中到如何一网站,一事本,如何
,它完全是在程序的基本能力,而不是“技”。一言以蔽之, 就是在教怎麽写程式。很推
荐大一同学和程式初学者读这本, 这本书并不是进阶书而是入门书哦! 但这不表示它很好
读, 请有心理准备。和一般的程式语言书籍不同, 里头的数学味道很重, 几乎都是数学题
目, 牛顿法、最大公因数、微分, 有理数/复数的运算, 真是不习惯。更不习惯的是他所
选用的语言是 lisp 系的 scheme, prefix syntax 让人迷惑, 这是吸引我的最主要部份
, 据说 2008 年已经改用 python (好像是 2009), 若是 python, 我也许就没兴趣了吧!
看着一堆小括号充满萤幕, 真是有趣。
4.1.1 ~ 4.1.4 会写一个 scheme interpreter, 我觉得还是照课本使用 scheme 来读
sicp, 比较不会有和课本出入的地方。
这本教科书我读来实在辛苦, 觉得很难, 所以读得很慢, 不知道是不是因为简体中文的翻
译, 我觉得又让她更难读了。者裘宗燕老师学问应该很好, 不过翻译可能不是他的强项 (
他翻译过很多不错的原文书籍)。
In a production-quality Lisp system,
书中翻成 "在产品质量的 Lisp 系统里", 说实在, 我得看原文才懂这句话。这英文不算
难懂, 但要翻译成通顺的句子那就不容易了。
It calls apply-primitive-procedure to apply primitives;
书上翻译: 它直接调用 apply-primitive-procedure 去应用基本过程
我把它改为: 它直接呼叫 apply-primitive-procedure 去执行 primitives procedure。
To define a variable, we search the first frame for a binding for the
variable
我们需要在第一个框架查找该变量的约束
descent 改: 我们需要在第一个框架查找该变数的定义
还真的不好翻译, 只看中文会看不懂, 查询完原文後就好多了。
This computation will run much more slowly than a gcd procedure written in
Scheme, because we will simulate low-level machine instructions, such as
assign, by much more complex operations.
书上翻译为:
因为我们是在模拟低级的机器指令, 例如 assign, 而使用的却是比他高级得多的操作。
这句话也是怪怪的。
书中的句子有很多像是这样的翻译, 读来不能算是轻松, 我偶尔得对照一下原文词句。
就算翻译的不算好, 但中文版本还是帮了我不少忙, 这本并没有烂到完全看不懂, 大多时
候还是可以理解翻译後的意思, 没有中文翻译, 我无法那麽快浏览过一遍, 有些翻不好的
地方如果不是关键处, 倒也无伤大雅。加上对照原文, 对於英文不好的我来说, 甚有帮助
, 这是翻译的价值。与其要求每个人把英文、日文、德文、法文学好, 才能吸收其中的专
业知识, 倒不如用国家力量培养优秀的翻译人员。
(
http://goo.gl/z3Rje1 )
目
前 言
第1章 构造程抽象
1.1 程序的基本元素
1.2 程与它所生的算
1.3 用高函做抽象
第2章 构造据象
2.1 据抽象引
2.2 次性据和包性
2.3 符据
2.4 抽象据的多重表示
2.5 有通用型操作的系
第3章 模化、象和
3.1 值和局部
3.2 求值的境模型
3.3 用据做模
3.4 并:是一本
3.5 流
第4章 元言抽象
4.1 元循求值器
4.2 Scheme的形——惰性求值
4.3 Scheme的形——非确定性算
4.4 程序
第5章 寄存器机器里的算
5.1 寄存器机器的
5.2 一寄存器机器模器
5.3 存分配和料收集
5.4 式控制的求值器
5.5
这是本怎麽样的书呢? 主要在教如何写程式, 以及程式是怎麽样的一个东西。前两章对一
个有涉猎程式的人来说, 大概都能明白, 也就是一般 c++ 程式入门书籍上都会谈到的概
念。
资料抽象 - 将资料结构和操作的函数分开, 形成一个黑箱, 资料结构的改变不会影响这
些操作函数, 将修改程度降到最低。这不是一般的 c++ 程式书籍都会提到的资料封装吗
。
用不同的资料结构来表示同一个抽象资料, 书中提到复数的例子, 可以用直角座标或是极
座标 (很久没听到这名词了吧?) 来表示复数, 但也必须要在这两种资料结构做转换。都
是表示复数, 没道理处理直角座标的程式码无法在极座标上执行, 该怎麽做呢? 最直观就
是提供转换的函式, 这不也是在程式设计中会看到的技巧。c++ 可以实作 cast
operator 和这个观念很类似。
再来型别转换一多的话, 程式码会太复杂, 能辨识出型别的操作函数不是很棒, 怎麽做?
加个 tag 判断即可。这不就是 if/switch/case 的应用吗?
if circle do_circle
else do_others
而 c++ 为了消除太多 if/switch/case 导入了 virtual function, 这边也用了类似表格
法来处理这样的问题, 类似 c 的 function pointer。这些技巧都不会因为用什麽语言而
有所不同, 是基本中的基本。
但从第三章开始, 就不是一般程式设计书籍提到的东西了, 你曾经想过变数与变数值的对
应是怎麽实作的吗? 在 script language 里头, 执行一个 expression 时会发生怎麽样
的行为呢? 函式的参数如何替换成真正的值? 3.2 有个概括的说明。
而第四章第五章的 metacircular evaluator, register base machine 更不是容易见到
的主题。我实在很怀疑这样的书籍竟然只是定位在入门等级。
从第一章看起 ...
1.1.1 谈 expression
1.1.4 利用 define 来建立 procedure (如同 c function)
1.1.5 谈到了 applicative order, normal order, p13 练习 1.5 有个有趣的题目:
1.5.scm
1 (define (p) (p))
2
3 (define (test x y)
4 (if (= x 0)
5 0
6 y))
当执行 (p) 会怎麽样, (p) 会先去找出 p 是什麽, 结果又找到 (p), 然後又去找 p 是
什麽 ... 永远都找不到, 这就是 applicative order。
而 normal order, 就很顺利执行完毕, 因为 normal order 不需要把 p 计算出来, 有需
要的时候在计算即可。
在 mit-scheme 可以使用 delay 这个函数来执行 normal order, (delay (p)) 就不卡住
了。
ref:
http://www.gnu.org/software/mit-scheme/documentation/mit-scheme-ref/Promises.html
(
http://goo.gl/WQTueY )
http://practical-scheme.net/gauche/man/gauche-refe_59.html#Delay-force-and-lazy
(
http://goo.gl/TFbVXL )
1.1.6 conditional expressions and predicate, 就是 if/else 用法。
这样读过来之後, 就可以开始用 scheme 写程式了。不过和 c 语言不同, 没有
for/while loop 这种东西, 那替代品是什麽呢? 是让人伤透脑筋的 recursive。
1.1.7 从牛顿法开始求根号 X, 正常人应该都忘记什麽是牛顿法, 只记得牛顿是谁吧?
square_root.scm
1 (define (sqrt-iter guess x)
2 (if (good-enough? guess x)
3 guess
4 (sqrt-iter (improve guess x)
5 x)))
6
7 (define (improve guess x)
8 (average guess (/ x guess)))
9
10 (define (average x y)
11 (/ (+ x y) 2))
12
13 (define (good-enough? guess x)
14 (< (abs (- (square guess) x)) 0.001))
15
16 (define (sqrt x)
17 (sqrt-iter 1.0 x))
18
19 (sqrt 2)
in mit-scheme
2 error> (load "square_root.scm")
;Loading "square_root.scm"... done
;Value: 1.4142156862745097
书上有写的东西就不说明了, 这种语法, 还真是不习惯。
1.2.1 linear recursion and iteration, 介绍 recursive 和 iteration, 书中用了两
个 factorial 来解释。
factorial.scm
1 ; recursive
2 (define (factorial n)
3 (if (= n 1)
4 1
5 (* n (factorial (- n 1)))))
6 (factorial 5)
7
8 ; iteration
9 (define (factorial n)
10 (fact-iter 1 1 n))
11
12 (define (fact-iter product counter max-count)
13 (if (> counter max-count)
14 product
15 (fact-iter (* counter product)
16 (+ counter 1)
17 max-count)))
iteration 的版本看起来好像是 recursive, 但这和 c 语言的 while, for loop 是一样
的概念。
1.2.3 介绍计算所需的时间, 计算所需要的记忆体空间。
1.3.2 介绍 lambda, 不过我觉得 the roots of lisp (
http://goo.gl/efetP ) 解释的
比较好。
(lambda (x) (+ x 4)) 这个是 function。
((lambda (x) (+ x 4)) 5) => 9 这叫 function call。
5 是 argument (引数), x 是 parameter (参数), (+ x 4) 是 function body。
lambda 建立的是一个没有名字的函数, 要使用这个函数就要用上述的那个语法。配合上
define, 就可以将这个 function 对应到一个名字。
(define plus4 (lambda (x) (+ x 4)))
也可以写成
(define (plus4 x) (+ x 4))
这是一种语法糖衣。
let 也是一种 lambda 的语法糖衣。
page 42
(define (f x y)
((lambda (a b)
(+ (* x (square a))
(* y b)
(* a b)))
(+ 1 (* x y))
(- 1 y)))
(define (f x y)
(let ((a (+ 1 (* x y)))
(b (- 1 y)))
(+ (* x (square a))
(* y b)
(* a b))))
let 的功能, 可以由 lambda 来提供。
1.3.3 将一个 procedure 当作参数传给一个 procedure
1.3.4 传回一个 procedure, 这还真难懂, 花了我好些时间。
(define (average-damp f)
(lambda (x) (average x (f x))))
真的很难懂吧!
first-class elements:
They may be named by variables.
They may be passed as arguments to procedures.
They may be returned as the results of procedures.
They may be included in data structures. (
http://goo.gl/aLumTA )
符合这些条件的 function 就称为 first-class function, 又是一个流行的名词。当然
符合这些条件的 object 就是 first-class object, 当然符合这些条件的 people 就是
first-class people XD
这是由 the British computer scientist Christopher Strachey (1916-1975) 帮我们
整理出来的概念。
(
http://goo.gl/Pbx731 )
2.1.1 p56 介绍了 pair, 有相关的操作函数 cons, car, cdr, list (p66, 为了方便使
用 cons, scheme 提供了 list) p57 最下面的注解解释了 cons, car (Contents of
Address part of Register, cdr (Contents fo Decrement part of Register) 这几个
奇怪的名称。
2.1.3 p61 实作了 cons, car, cdr。
(define (cons x y)
(define (dispatch m)
(cond ((= m 0) x)
((= m 1) y)
(else (error "Argument not 0 or 1 -- CONS" m))))
dispatch)
(define (car z) (z 0))
(define (cdr z) (z 1))
(car (cons x y))
(cdr (cons x y))
cons 会传回一个 procedure, 就是 dispatch, 再用来和 car, cdr 一起运作。
2.2.1 p67 提到 (cadr [arg]) = (car (cdr [arg])) 这样的缩写方式, 免得写很多
car, cdr ...
2.2 Hierarchical Data and the Closure Property, 这个 Closure 不是你想的那种,
这是指这个资料结构可以一直的串下去。
(
http://goo.gl/mzQOmx )
(
http://goo.gl/RPd2KQ )
cons 最主要就是一个 pair 结构, (cons 1 (cons 2 (cons 3 '() ))) 这样的资料结构
就是由这些 pair 一个一个串接起来, 别小看这麽简单的东西, 这除了可以表达很直观的
sequence 结构外, 还可以看做是一颗树的结构。在 3.3.2 还会用这个来表示 queue,
用这样的方式:
(
http://goo.gl/qyaeeD )
很难懂, 我花了一天才搞懂这个 queue 的表达方式。
ref:
http://goo.gl/BSw0vE (
http://descent-incoming.blogspot.tw/2014/08/implement-queue-by-mit-scheme.html
)
2.3.3 以集合 (sets) 为范例, 以 list (排序和未排序两种 list) 和 tree 为资料结构
, 实作加入一个元素到集合里头, 某个元素是否在这个集合, 找出差集和联集。
scheme 当然没有类似 c 的 struct 这种东西, 书中用 list 来模拟 tree。
2.4.3 有提到一个 message passing 的设计方式。
3.1 这节在描述 assginment 和 local 变数的行为。
3.1.1 导入了 set! 用来做 assginment。
3.1.3 说明了 functional programming 和 imperative programming。
functional programming wiki 上的解释
In computer science, functional programming is a programming paradigm, a
style of building the structure and elements of computer programs, that
treats computation as the evaluation of mathematical functions and avoids
state and mutable data.
函数式编程(英语:Functional programming)或者函式程式设计,又称泛函编程,是一
种编程典范,它将电脑运算视为数学上的函式计算,并且避免使用程式状态以及易变物件
。
相信你看得一头雾水。来看 sicp 3.1.1 的解释:
sicp 3.1.3
Programming without any use of assignments, as we did throughout the first
two chapters of this book, is accordingly known as functional programming.
函数式程式设计原来就是这样定义, 之前都搞不懂。网路有些文章还写像数学函数那样来
写程式 (大概都是抄 wiki 的吧), 数学函式我知道, 但还是不知道什麽是函数式程式。
看些讨论讲得好神, 不过基本就是这样。而采用 assignments 的称为 imperative
programming。没用 assignments 的就是函数式程式设计。
不过我觉得书上提到的 assignment 比较像是使用 c 的 static variable 作
assignment 的动作。
难怪在这前两章的范例程式时, 就觉得哪里怪怪的, 没错, 我都没看到 assignment 的概
念。原来没 assignment 也是可以写程式的。
自制编程语言 page 7 写的更直接: 「变数值无法被更改」的语言就是函数式编程语言。
我觉得这更容易理解, 一句话道出 functional programdming 真谛。
factorial_1.scm functional programming
1 (define (factorial n)
2 (define (iter product counter)
3 (if (> counter n)
4 product
5 (iter (* counter product)
6 (+ counter 1))))
7 (iter 1 1))
8
9 (factorial 5)
factorial_2.scm imperative programming
1 (define (factorial n)
2 (let ((product 1)
3 (counter 1))
4 (define (iter)
5 (if (> counter n)
6 product
7 (begin (set! product (* counter product))
8 (set! counter (+ counter 1))
9 (iter))))
10 (iter)))
11
12 (factorial 6)
上述程式码便是分别展示这两种编程方式。
3.2 在说明引进 assignment 之後, 整个程式的运作模型。很重要, 也很难理解, 我花了
不少时间在这边。
3.2.1 说明了当定义一个 procedure (在 scheme 只能用 lambda 产生一个
procedure), 或使用 define (这只是一个语法糖衣, 实际是用 lambda 产生一个
procedure) 产生一个 procedure 时, 怎麽将这个 procedure 和该名字关联在一个环境
里。而这个 procedure object 包含两部份, 一个是 procedure code 本身 (含型式参数
部份), 一个是环境 (可能是一个指到某个环境的指标)。
在呼叫这个 procedure 时, 传入的真正参数是怎麽和 procedure 的参数产生关联, 这时
後会建立一个新的环境/frame, 而呼叫这个 procedure 的环境便成为这个新环境的上层
环境。
这节一开始我并没有完全看懂, 而是看懂 4.1 metacircular evaluator source code 这
部份的程式码时, 我回头看了好几次才看懂。也因为 bind 被翻译成约束, 有些句子也成
为阅读障碍, 建议对照原文, 应该会比较清楚。
虽然翻译有些问题, 但我还是觉得中文版本帮上不少忙, 当然有原文对照会比较好些。若
是没有中文版本, 我阅读的速度绝对不能这麽快。
这里的解释很重要, 是变数代换和 procedure 求值的关键, 若真看不懂, 只好看 4.1
metacircular evaluator source code。两相对照, 相得益彰。
关键点有两个:
evaluate 一个 procedure 时, 建立 procedure object (一个 pair, 其中是 function
body, 另一个是环境指标, 指到某个环境), 环境指标的上层环境是谁也要清楚。
apply 一个 procedure 时, 环境是怎麽建立 (会建立一个新环境), 上层环境是谁? 如何
将变数值对应到函式的参数。
(define (square x) (* x x)) 这是 evaluate
(square 5) 这是 apply
3.2.2, 3.2.3 3.2.4 以三个实际的程式码, 分别说明了, 环境如何建立, 对应的变数如
何与实际的变数值对应起来, 不算好懂, 得花点脑力才行。不过这个观念很重要, 可以得
知变数是怎麽关联起来的, 为什麽同名称的变数不会互相干扰, 独立对应到不同的值。
要搞懂 interpreter, 3.2 这部份的东西要有清楚的认知。
3.2.3 的例子:
withdraw.scm
1 (define (make-withdraw balance)
2 (lambda (amount)
3 (if (>= balance amount)
4 (begin (set! balance (- balance amount))
5 balance)
6 "Insufficient funds")))
7
8 (define W1 (make-withdraw 100))
9 (W1 50)
10 (W1 20)
说明环境怎麽用来维护 balance 这个局部变数, 有点像是 c 的 static 变数。
3.3.1 则介绍了 set-car!, set-cdr! 来改变一个 list。
change_list
1 1 ]=> (define alist (list 1 2))
2
3 ;Value: alist
4
5 1 ]=> (display alist)
6 (1 2)
7 ;Unspecified return value
8
9 1 ]=> (set-car! alist 5)
10
11 ;Unspecified return value
12
13 1 ]=> (display alist)
14 (5 2)
15 ;Unspecified return value
3.4 concurrency: Time is of the essence 提出撰写 concurrency 程式的问题, 以及
利用 mutex 来处理共享资源。在目前这麽流行的 thread 环境中, 这些都是大家朗朗上
口的概念, 但这本书可是很早就讨论了这些东西, 而就算大家朗朗上口这些概念, 把
thread 程式写好也不是件容易的事。
chapter4 是很精彩的一章, 4.1 要写出一个 metacircular evaluator, 讲白话就是用
lisp 写出一个 lisp interpreter, 这里的实作当然是 scheme。基本上只要读到 4.1.4
就有个可以执行 scheme 的 interpreter, 是不是很兴奋阿! 这可说是我读这本书的最大
动力了, 好久好久以前就想知道 interpreter 是怎麽做的。
如果你觉得 chapter 1, 2, 3 已经很难, 那我得告诉你, 这章更难, 得要有花更多时间
的心理准备, 不过好消息是: 这章不是最难的, 後面那章更难。
我飞快阅读过前面三章, 略过习题, 就是为了可以尽快看到这章。我把精力花在 4.1.1
~ 4.1.4, 并以 c++ 实作了相同的版本。也许这样讲夸张了点, 光读这四小结的时间可抵
上 1, 2 章。
只要读完这四个小节, 就可以写出四则运算、自订变数、函式呼叫、判断式的直译器,
The unix programming environment 可是用了一章 (第八章) 在讲这些东西, 应该是最
简单的文件了。不过我得先告诉你, 我可是花了至少一个月的时间才真的搞懂, 研究直译
器真的很有趣, 但真的很花时间、精力。
4.1.5
(eval '(* 5 5) user-initial-environment)
(eval (cons '* (list 5 5)) user-initial-environment)
eval 需要带入一个环境
4.1.6 提到了 internal definitions, 看以下的程式码:
(define (f x)
(define (even? n)
(if (= n 0)
true
(odd? (- n 1))))
(define (odd? n)
(if (= n 0)
false
(even? (- n 1))))
)
虽然在 even? 内用到 odd?, 但这应该难不倒你, 这个程式可以正常执行。
Exercise 4.19.
(let ((a 1))
(define (f x)
(define b (+ a x))
(define a 5)
(+ a b))
(f 10))
这个呢? (f 10) 会得到 20 还是 16 还是发出错误讯息? 难倒你了吧? 在 mit-scheme
是发出错误讯息, 我也喜欢这样的实作方式。
chapter 5 则更进一步, 打造一台模拟机器, 让你在上头跑 scheme 的程式。和 java 的
virtual machine (stack base) 不同, sicp 介绍的是 register base machine。这章
也是要燃烧很多的脑力, 难度比第四章略难。
5.1 介绍了计算 GCD, factorial 的机器设计流程。
5.1.1 用了一个描述暂存器机器的语言, 如下:
gcd
1 (controller
2 test-b
3 (test (op =) (reg b) (const 0))
4 (branch (label gcd-done))
5 (assign t (op rem) (reg a) (reg b))
6 (assign a (reg b))
7 (assign b (reg t))
8 (goto (label test-b))
9 gcd-done)
这是用来描述一个计算 GCD 的机器, 只要把暂存器 a, b 存入两个数字, 机器运算後,
会在暂存器 a 得到这两个数的 GCD。
5.2 实作模拟器程式码, 跑一下哪个 GCD 机器。
5.4 将写出一个 explicit-control evaluator, 用来执行 4.1 的那个 metacircular
evaluator, 真是太酷了!
有一个 scheme chip, 可参考:
Batali, J. et al. "The Scheme-81 Architecture—System and Chip." Proc.
Conference on Advanced Research in VLSI, P. Penfield Jr. ed., MIT, 1982, pp.
69-77.
不过我找不到文章内容。
5.5 提到编译这个主题, 和 5.4 的 interpreter 对照, 两个不同的执行方式, 可以体会
其中的优缺点。
5.5.7 会示范如何将 compile 後的 code 载入到模拟的机器执行。
这章一样是要花费很大的时间、脑力, 本科系的朋友应该会很喜欢这些主题。
网路上有很多本书的讨论讯息, 但如果你没看过这本书, 应该还是不知道这本书在说什麽
(我认为是他们没有完全读完这本书, 再说一次, 这本书我觉得不好读, 当然还是比我读
的 os 书籍容易些; 如果你听过程式设计师的自我修养 - 连结、载入、程式库这本书,
我觉得 sicp 比这本还难读), 希望这篇文章能让你了解个大概, 也能吸引你去读这本书
。当然没有哪本书是一定非读不可, 你总是可以从其他地方或取相同的知识, 要得到本书
的知识也并非要从本书开始。网路评价很好的书籍也并非就一定要读。
这两篇评论写的很好, 一看就知道是有看过整本书的人所写:
http://book.douban.com/review/4559081/ (
http://goo.gl/r87yC3 )
http://book.douban.com/review/4987015/ (
http://goo.gl/SXI97 )
1996 的书过时了吗? 我不认为, 光是第四章、第五章就值回票价。你去哪找两章就可以
讲解/完成一个 interpreter 和 register base machine 的书。
相关资料
nil cannot work:
http://goo.gl/O63OHC (
http://stackoverflow.com/questions/9115703/null-value-in-mit-scheme )
使用 '() 来代替 nil
ref:
SICP (1) :
http://goo.gl/IXZk3 (
http://kidneyball.iteye.com/blog/922953 )
老托 (2): 算机程序的构造与解 (
http://goo.gl/jVCEg )
SICP 解集 (
http://goo.gl/2x0YdM )
线上课程:
http://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/
(
http://goo.gl/DRqq )
sicp code:
http://mitpress.mit.edu/sicp/code/index.html (
http://goo.gl/Xz0NxD )
sicp epub version:
https://github.com/ieure/sicp (
http://goo.gl/dlyTH )
Recursive Functions of Symbolic Expressions and Their Computation by Machine,
Part I by John McCarthy:
pdf2 (
http://goo.gl/eXkyHP ).
简体中文字幕 sicp 课程:
http://v.youku.com/v_show/id_XNTMxODY1NTg4.html (
http://goo.gl/WW8BPA )
这是课程的其中一部分, 有兴趣的朋友可自行搜寻其他部份。
// 本文使用 Blog2BBS 自动将Blog文章转成缩址的BBS纯文字
http://goo.gl/TZ4E17 //
blog 原文:
http://descent-incoming.blogspot.tw/2014/11/books-sicp-2nd-edition.html
--
钱要是不花, 它就是纸。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 58.114.144.105
※ 文章网址: http://webptt.com/cn.aspx?n=bbs/CompBook/M.1417963326.A.5A5.html
※ 编辑: descent (58.114.144.105), 12/07/2014 22:47:28
1F:推 saladim : 先推 12/08 02:55
2F:推 abandonONE : 推 12/10 11:50
※ 发信站: 批踢踢实业坊(ptt.cc)
※ 转录者: descent (180.217.251.209), 06/02/2015 20:11:42
3F:推 NilPtr: 推 06/04 14:38
4F:推 icycandle: 感激,这样的心得太实用了 :D 06/20 14:21
5F:推 art1: 光看简中翻译会觉得这是机翻 08/27 00:05
6F:推 caasih: 给跪了 <O> 04/14 03:48
7F:推 CoNsTaR: 推 08/20 02:38