Structure And Interpretation Of Computer Programs (SICP)

计算机程序的构造和解释

1. scheme的美妙

scheme美观打印的格式规则,键值对

(+ (* 3
       (+ (* 2 4)
          (+ 3 5)))
    (+ (- 10 7)
       6))

Lisp的语法非常简单,对各种表达式的求值规则:
可以描述为一个简单的通用规则和一组针对不多的特殊形式的专门规则

过程定义的一般形式:

(define ( ) )

(define (square x) (* x x))
(define (abs x)
  (cond ((> x 0) x)
        ((= x 0) 0)
        ((< x 0) (- x))))
**句法**
(cond ( )
      ( )
      ( )
)
(if   )

** 最常用的三个符合运算符:**

  1. (and … )
  2. (or … )
  3. (not )

构造数据抽象

能够构造复合数据对象的能力,可以处理与数据有关的各种问题

(make-rat )
(numer )
(denom

Lisp 表结构数据

数组的address的由来

过程 全称 解释
cons constrcut 构造
car contents of address part of register 寄存器的地址部分的内容
cdr contents of decrement part of register 寄存器的减量部分的内容

闭包性质:
组合起数据对象得到的结果本身还可以通过同样的操作再进行组合。

人生第一个知道的拉丁词汇: nihil (虚无,毫无价值)

fringe:穗;非重要,次要的

使用约定的界面

在工程设计中,模块化结构式控制复杂度的一种威力强大的策略

一个图形语言

展示数据抽象和闭包的威力

描述一种语言时,应该将注意力集中到语言的基本原语,它的组合手段以及它的抽象手段,这是最重要的。

wave: 挥手;舞动;波浪
roger: 已收到,明白;v,sex

vert: 绿色;森林中的草木;绿色的

2. 模块化、对象和状态

在这一章里,我们要研究两种特点很鲜明的组织策略,它们源自对系统结构的两种非常不同的“世界观”。
第一种策略将注意力集中在对象上,将一个大型系统看成一大批对象,它们的行为可能随着时间的进展而不断变化。
另一种组织策略将注意力集中在流过系统的信息流上,非常像电子工程师观察一个信号处理系统。
即,基于对象的途径和基于流处理的途径。

局部状态变量
withdraw 取现金
insufficient funds金额不足
balance 平衡,均衡;账户余额

实践出真知

(+ 137 349)
(- 1000 334)
(* 5 99)
(/ 10 5)
(+ 2.7 10)
(+ 21 35 12 7)
(* 25 4 12)
(+ (* 3 5) (- 10 6))
(+ (* 3
      (+ (* 2 4)
         (+ 3 5)))
   (+ (- 10 7)
      6))

(define size 2)
size
(* 5 size)
(define pi 3.14159)
(define radius 10)
(* pi (* radius radius))
(define circumference (* 2 pi radius))
circumference

# out
486
666
495
2
12.7
75
1200
19
57
2
10
314.159
62.8318

circumference 周长

一个List程序通常总是由一大批相对简单的过程组成

(define (square x)
  (* x x))
(square 21)
(square (+ 2 5))
(square (square 3))

(define (sum-of-squares x y)
  (+ (square x) (square y)))
(sum-of-squares 3 4)

(define (f a)
  (sum-of-squares (+ a 1) (* a 2)))

(f 5)

# out
441
49
81
25
136
  • 完全展开而后归约的求值模型称为 正则序求值
  • 先求值参数而后应用的方式称为 应用序求值

条件表达式谓词

练习1.1

(define (ju x)
(and (> x 5) (< x 10)))

(ju 7)


10
(+ 5 3 4)
(- 9 1)
(/ 6 2)
(+ (* 2 4) (- 4 6))

(define a 3)
(define b (+ a 1))
(+ a b (* a b))
(= a b)
(if (and (> b a) (< b (* a b)))
    b
    a)
(cond ((= a 4) 6)
      ((= b 4) (+ 6 7 a))
      (else 25))

(+ 2 (if (> b a) b a))

(* (cond ((> a b) a)
         ((< a b) b)
         ((else -1)))
         (+ a 1))
   
# out
10
12
8
3
6
19
#f
4
16
6

练习1.2

(/ (+ 5 4 (- 2 (- 3 (+ 6 (/ 4 5)))))
   (* (- 6 2) (- 2 7)))

-37/50

练习1.3



(set! )

(begin … )
表达式 到将按顺序求值,并且将最后一个表达式的值作为整个begin形式的值返回

scheme语法习惯里,赋值的操作都被以一个感叹号结尾;类似以问号结尾的名字表示谓词的习惯。

(define (make-account balance)
  (define (withdraw amount)
    (if (>= balance amount)
        (begin (set! balance (- balance amount))
               balance)
        "Insufficient found"))
  (define (deposit amount)
    (set! balance (+ balance amount))
    balance)
  (define (dispatch m)
    (cond ((eq? m 'withdraw) withdraw)
          ((eq? m 'deposit) deposit)
          (else (error "Unknown request -- MAKE-ACCOUNT"
                       m))))
  dispatch)

(define acc (make-account 100))

((acc 'withdraw) 50)

((acc 'withdraw) 60)

((acc 'deposit) 40)

((acc 'withdraw) 60)

第三章

计算机里的时间和现实世界的时间之间的关系??

3.2节 描述求值的环境模型??

第四章 元对象抽象

元语言抽象就是建立新的语言。通过构造求值器可以实现这些语言。
求值器就是解释器:应用于这个语言的一个表达式时,它能够执行求值这个表达式所要求的工作。

组合手段和抽象手段

  • 多项式的算术规则
  • 数字逻辑模拟器
  • 约束传播系统

正则序求值??

4.4 节实现了逻辑程序设计语言??

元循环?? 用解释器的语言同样的语言写出来的解释器,称为元循环

求值器里两个关键过程:eval和applay的相互作用。??

一个新语言:

  1. 求值器使我们能够处理嵌套的表达式,(+ 1 (* 2 3))
  2. 求值器使我们可以使用变量
  3. 求值器使我们可以定义复合过程。
  4. 求值器还要提供一批特殊形式,它们的求值方式与普通过程调用不同

揭示计算机语言本质的eval-apply循环:

  1. 过程,实际参数(eval)
  2. 表达式,环境(apply)
(make-procedure (
      lookup-variable-value
      apply-primitive-procudure
)
)

求值器的内核

eval

基本表达式

  1. 对于自求值表达式,例如各种数,eval直接返回这个表达式本身
  2. eval必须在环境中查找变量,找出他们的值

特殊形式

  1. 对于加引号的表达式,eval返回被引的表达式
  2. 对于变量的赋值(或定义),就需要递归地调用eval去计算出需要关联这个变量的新值
  3. 一个if表达式要求对其中各部分的特殊处理方式,在谓词为真时求值其推论部分,否则就
    求值其替代部分
  4. 一个lambda必须被转换成一个可以应用的过程,方式就是将这个lambda表达式所描述的参数表和体与
    相应的求值环境包装起来
  5. 一个begin表达式要求求值其中的一系列表达式,按照它们出现的顺序
  6. 分情况分析(cond) 将被变换为一组嵌套if表达式,而后求值

组合式

  1. 对于一个过程应用,eval必须递归地求值组合式的运算符部分和运算对象部分,而后将这样得到的过程和参数送给apply,由它去处理实际的过程应用

eval的定义

;; quotatoin引用,引文
(define (eval exp env)
  (cond ((self-evaluating? exp) exp)
        ((variable? exp) (lookup-variable exp env))
        ((quoted? exp) (text-of-quotation exp))
        ((assignment? exp) (eval-assignment exp env))
        ((definition? exp) (eval-definition exp evn))
        ((if? exp) (eval-if exp env))
        ((lambda? exp)
         (make-procedure (lambda-parameters exp)
                         (lambda-body exp)
                         env))
        ((begin? exp)
         (eval-sequence (begin-actoins exp) env))
        ((cond? exp) (eval (cond->if exp) env))
        ((application? exp)
         (apply (eval (operator exp) env)
                (list-of-values (operands exp) env)))
        (else
         (error "Unknown expression type -- EVAL" exp))))
apply

apply有两个参数,一个是过程,一个是该过程应该去应用的实际参数的表

  1. 直接调用apply-primitive-procedure去应用基本过程
  2. 应用符合过程的方式是顺序地组成该过程体的那些表达式
(define (apply procudure arguments)
  (cond ((primitive-procedure? procedure)
         (apply-primitive-procedure procedure arguments))
        ((compound-procedure? procedure)
         (eval-sequence
          (procedure-body procedure)
          (extend-environment
           (procedure-parameters procedure)
           arguments
           (procedure-environment procedure))))
        (else
         (error
          "Unknown procedure type -- APPLY" procedure))))
过程参数

eval在处理过程应用时用list-of-values去生成实际参数表

;; 操作数;运算对象
(define (list-of-values exps env)
  (if (no-operands? exps)
      '()
      (cons (eval (first-operand exps) env)
            (list-of-values (rest-operands exps) env))))
条件

eval-if在给定环境中求值if表达式的谓词部分,如果得到为真,结果为真
eval-if就去求值这个if的推论部分,否则它就求值替换部分

;; predicate谓语;使基于,断言
(if ()
    () ;; if-predicate is true
    () ;; if-predicate is false
    )
;; consequent 由此发生;后件,推断
;; alternative备选的
(define (eval-if exp env)
  (if (true? (eval (if-predicate exp) env))
      (eval (if-consequent exp) env)
      (eval (if-alternative exp) env)))
序列

eval-sequence用在apply里,用于求值过程体里的表达式序列,它也用在eval里
用于求值begin表达式里的表达式序列,这个过程以一个表达式序列和一个环境为参数,按照
序列列表里的表达式出现的顺序对它们求值,它返回最后一个表达式的值

(define (eval-sequence exps env)
  (cond ((last-exp? exps) (eval (first-exp exps) env))
        (else (eval (first-exp exps) env)
              (eval-sequence (rest-exps exps) env))))
赋值和定义

下面的过程处理变量赋值,它调用eval找出需要赋的值,将变量和得到的值传给过程set-variable-value!,将有关的值安置到指定环境里

(define (eval-assignment exp env)
  (set-variable-value! (assignment-variable exp)
                       (eval (assignment-value exp) env)
                       env)
  'ok)

(define (eval-definition exp env)
  (define-variable! (definition-variable exp)
    (eval (definition-value exp) env)
    env)
  'ok)
表达式的求值
  1. 这里的自求值表达式只有数字和字符串
(define (self-evaluating? exp)
  (cond ((number? exp) true)
        ((string? exp) true)
        (else false)))

  1. 变量用符号表示
(define (variable? exp)
  (symbol? exp))

  1. 引号表达式的形式是(quote )
(define (quoted? exp)
  (tagged-list? exp 'quote))

(deifne (text-of-quotation exp)
        (cadr exp))

(define (tagged-list? exp tag)
  (if (pair? exp)
      (eq? (car exp) tag)
      false))
  1. 赋值的形式是(set! )
(define (assignment? exp)
  (tagged-list? exp 'set!))

(define (assignment-variable exp) (cadr exp))

(define (assignment-value exp) (caddr exp))
  1. 定义的形式是 (define ) 或者 (defien ( … ))
    后一种定义是标准的过程定义
(define 
  (lambda (  ... )
    ))

;; tagged标记的
(define (definition? exp)
  (tagged-list? exp 'define))

(define (definition-variable exp)
  (if (symbol? (cadr exp))
      (cadr exp)
      (caadr exp)))

(define (difinition-value exp)
  (if (symbol? (cadr exp))
      (caddr exp)
      (make-lambda (cdadr exp) ; formal parameters
                   (cddr exp)))) ; body

lambda表达式是由符号lambda开始的表

(define (lambda? exp) (tagged-list? exp 'lambda))

(define (lambda-parameters exp) (cadr exp))

(define (labmda-body exp) (cddr exp))

lambda表达式提供了一个构造函数

(define (make-lambda parameters body)
  (cons 'lambda (cons parameters body)))

条件式由if开始,有一个谓词部分predicate,一个推论部分consequent,一个可缺省的替换部分alternative

(define (if? exp) (tagged-list? exp 'if))

(define (if-predicate exp) (cadr exp))

(define (if-consequent exp) (caddr exp))

(define (if-alternative exp)
  (if (not (null? (cdddr exp)))
      (cadddr exp)
      'false))

为if表达式提供一个构造函数,它在cond-if中使用


(define (make-if predicate consequent alternative)
  (list 'if predicate consequent alternative))

begin包装起要给表达式序列

(define (begin? exp) (tagged-list? exp 'begin))

(define (begin-actions exp) (cdr exp))

(define (last-exp? seq) (null? (cdr seq)))

(define (first-exp seq) (car seq))

(define (rest-exps seq) (cdr seq))

构造函数sequence->exp,它把一个序列变换为一个表达式,如果需要的话就加上begin作为开头

(define (sequence->exp seq)
  (cond ((null? seq) seq)
        ((last-exp? seq) (first-exp seq))
        (else (make-begin seq))))

(define (make-begin seq) (cons 'begin seq))

(define (application? exp) (pair? exp))

(define (operator exp) (car exp))

(define (operands exp) (cdr exp))

(define (no-operands? ops) (null? ops))

(define (first-operand ops) (car ops))

(define (rest-operands ops) (cdr ops))

派生表达式
一些特殊形式的可以基于其他特殊形式的表达式定义出来,而不必直接去实现。


(cond ((> x 0) x)
      ((= x 0) (display 'zero) 0)
      (else (- x)))

;; 可以规约为下面涉及if和begin的表达式的求值问题
(if (> x 0)
    x
    (if (= x 0)
        (begin (display 'zero)
               0)
        (- x)))

;; 这里包含了提取cond表达式中各个部分的语法过程,以及过程cond->if
(define (cond? exp) (tagged-list? exp 'cond))

;; clause 子句
(define (cond-clauses exp) (cdr exp))

(define (cond-else-calause? clause)
  (eq? (cond-predicate clause) 'else))

(define (cond-predicate clause) (car clause))

(define (cond-actions clause) (cdr clause))

(define (cond->if exp)
  (expand-clauses (cond-clauses exp)))

  
(define (expand-clauses clauses)
  (if (null? clauses)
      'false   ; clause else no
      (let ((first (car clauses))
            (rest (cdr clauses)))
        (if (cond-else-clause? first)
            (if (null? rest)
                (sequence->exp (cond-actions first))
                (error "ELSE clause isn't last -- COND->IF"
                       clauses))
            (make-if (cond-predicate first)
                     (sequence->exp (cond-actions first))
                     (expand->clauses rest))))))

let表达式也被作为派生表达式,见练习 4.6

let*与let类似,但其中对let变量的约束时从左到右顺序进行的

(let* ((x 3)
       (y (+ x 2))
       (z (+ x y 5)))
  (* x z))

许多语言都支持多种迭代结构,例如:do, for, while 和util
在scheme里,迭代计算过程可以通过常规过程调用的方式表述

请为scheme设计和实现一种新的语法形式,通过数据抽象技术??

求值器数据结构

除了需要定义表达式的外部语法形式之外,求值器的实现还必须定义好在其内部实际操作的数据结构
,作为程序执行的一部分,例如,定义好过程和环境的表示形式,真和假的表示形式等等

谓词检测

除了false对象之外的所有东西都是接受为真

(define (true? x)
  (not (eq? x false)))

(define (false? x)
  (eq? x false))

处理基本过程
(apply-primitive-procedure )
它能够给定的过程应用于表里的参数值,并返回这一应用的结果

(primitive-procedure? )
检查是否为一个基本过程

处理基本过程的机制在 4.1.4节中详细讨论??

复合过程
(define (make-procedure parameters body env)
  (list 'procedure parameters body env))

;; compound 混合物,混合
(define (compound-procedure? p)
  (tagged-list? p 'procedure))

(define (procedure-parameters p) (cadr p))

(define (procedure-body p) (caddr p))

(define (procedure-environment p) (cadddr p))
对环境的操作

求值器需要对环境的一些操作
一个环境就是一个框架的序列,每个框架都是一个约束的表格, 其中的约束关联起一些变量和与之对应的值
(lookup-variable-value )
返回符号在环境里的约束值,如果这一变量没有约束就发出一个错误信号

(extend-environment )
返回一个新环境,这个环境中包含了一个新的框架,其中的所有位于表里的符号约束到表里对应的元素,而其外围环境是环境

(define-variable! )
在环境的第一个框架里加入一个新的约束,它关联起变量和值

(set-variable-value! )
修改变量在环境里的约束,使得该变量现在约束到值,如果这一变量没有约束就发出一个错误信号

;; enclosing封闭,围合
(define (enclosing-environment env) (cdr env))

(define (first-frame env) (car env))

(define the-empty-environment '())


(define (make-frame variables values)
  (cons variables values))

(define (frame-variables frame) (car frame))

(define (frame-values frame) (cdr frame))

(define (add-binding-to-frame! var val frame)
  (set-car! frame (cons var (car frame)))
  (set-cdr! frame (cons val (cdr frame))))

(define (extend-environment vars vals base-env)
  (if (= (length vars) (length vals))
      (cons (make-frame vars vals) base-env)
      (if (< (length vars) (length vals))
          (error "Too many arguments supplied" vars vals)
          (error "Too few arguments supplied" vars vals))))

要么在一个环境中查找一个变量,就需要扫描第一个框架里的变量表。如果找到了所需的变量,就返回与之对应的值表里的对应元素
如果在当前框架里找不到这个变量,就到其外围环境里去查找,并如此继续下去,如果遇到空环境,那么就发出一个“未约束变量”的错误

(define (lookup-variable-value var env)
  (define (env-loop env)
    (define (scan vars vals)
      (cond ((null? vars)
             (env-loop (enclosing-environment env)))
            ((eq? var (car vars))
             (car vals))
            (else (scan (cdr vars) (cdr vals)))))
    (if (eq? env the-empty-environment)
        (error "Unbound variable" var)
        (let ((frame (first-frame env)))
          (scan (frame-variable frame)
                (frame-values frame)))))
  (env-loop env))

在需要为某个变量在给定环境里设置一个新值时,我们也要扫描这个变量,就像在过程loopup-variable-value里一样,在找到这一变量后修改它的值

 (define (set-variable-value! var val env)
   (define (env-loop env)
     (define (scan vars vals)
       (cond ((null? vars)
              (env-loop (enclosing-environment env)))
             ((eq? var (car vars))
              (set-car! vals val))
             (else (scan (cdr vars) (cdr vals)))))
     (if (eq? env the-empty-environment)
         (error "Unbound variable -- SET!" var)
         (let ((frame (first-frame env)))
           (scan (frame-variable frame)
                 (frame-values frame)))))
   (env-loop env))

为了定义一个变量,需要在第一个框架里查找该变量的约束,如果找到就修改其约束,如果不存在这种约束,就在第一个框架中添加这种约束

(define (define-variable! var val env)
  (let ((frame (first-frame env)))
    (define (scan vars vals)
      (cond ((null? vars)
             (add-binding-to-frame! var val frame))
            ((eq? var (car vars))
             (set-car! vals val))
            (else (scan (cdr vars) (cdr vals)))))
    (scan (frame-variables frame)
          (frame-values frame))))

认知掌握一个东西的方式
重复熟悉的次数达到了解其细节的方方面面

将求值器描述为一个程序的一个优点是我们可以运行这个程序,这样就给了我们一个能够在Lisp里运行的,有关Lisp本身
如何完成表达式求值的工作模型,这一模型可以作为一个工作框架,使人能够去试验各种求值规则。

运气求值器

;; 如果这都还不足以明白程序的运行机制,那就没谁了
(define the-global-environment (setup-environment))
(driver-loop)

;; M-Eval input:
(define (append x y)
  (if (null? x)
      y
      (cons (car x)
            (append (cdr x) y))))
;;; m-Eval value:
ok

;;; M-Eval input:
(append '(a b c) '(d e f))
;; M-Eval value:
(a b c d e f)

第五章 寄存器机器里的计算

基于传统计算机的一步一步操作,描述一些计算过程,这类计算机叫寄存器机器。
他们能顺序地执行一些指令,对一组固定称为寄存器的寄存器单元的内容完成各种操作。

5.1 寄存器机器的设计

寄存器设计包括设计它的数据通路(寄存器和操作)和控制器,控制器实现操作的顺序执行。


(define (gcd a b)
  (if (= b 0)
      a
      (gcd b (remainder a b))))


(controller
 test-b
 (test (op =) (reg b) (const 0))
 (branch (label gcd-done))
 (assign t (op rem) (reg a) (reg b))
 (assign a (reg b))
 (assign b (reg t))
 (goto (label test-b))
 gcd-done)

;;
(data-paths
 
 (registers
  ((name a)
   (buttons ((name a<-b) (source (register b)))))
  ((name b)
   (buttons ((name b<-t) (source (register t)))))
  ((name t)
   (buttons ((name t<-r) (source (operation rem))))))
 
 (operations
  ((name rem)
   (inputs (register a) (register b)))
  ((name =)
   (inputs (register b) (constant 0))))
 
 (controller
  test-b
  (test =)
  (branch (label gcd-done))
  (t<-r)
  (a<-b)
  (b<-t)
  (goto (label test-b))
  gcd-done)

子曰:学而时习之,不亦悦乎
人的思维方式和行为习惯是具有连续性,物理上说有习惯性,该连续性的力量非常大,也即习惯的力量。
下一个小时或未来在处理的事情跟上一个小时和前一段时间所处理的事情一致或大概内容相同的概率非常大,人生中很多时候我们
都是同一时间段基本处理或面对相同的问题,所以结论是,想要提高下一个小时或未来做某件事的概率,就需要在上一个小时或上一段时间开始做某件事。

论据:

  • 人们星期一上班的时候会困倦,因为上一日即周日人们没有处于工作的状态,所以人的行为和思维没有了连续性,突然开始另一件事(工作),就会发生精力的极大消耗。
  • 无论大人还是小孩,都会在休息,娱乐的时候会时而想到自己需要学习或做作业或工作一会儿,但是会发生很难,最终在没有休息好和没有娱乐彻底的状态下,也没有
    处理自己的计划,因为上一刻人类的行为和思维会极大地决定着下一刻和未来将进行的事情,该概率非常大,且伴随极大的能量变化,从而得出结论,从休息娱乐中切换
    到学习和工作,本身就是消耗极大能量和不连续的转变,正确做法是让休息和娱乐的连续性持续到理想的状态,在新的一天的开始进行工作或学习,并将连续性持续到
    理想状态。
  • 上瘾对于某一个群体的伤害极大,毒瘾和烟瘾不仅摧毁个人且伤害家庭,上瘾背后的真相就是人类行为和思维具有连续性,上一刻从事有上瘾的事情,下一刻会继续从事
    的概率非常大,需要从上一件事情中切换到其他事情或状态,会非常消耗能量,极具不连续。解决方案是从上一刻,从上一个连续性中开始杜绝上瘾的事情,从而降低未来
    或下一刻继续从事上瘾的概率。

解释和编译

显式控制求值器

  1. 移植计算机语言到另一台机器,只需把显式控制求值器的指令,一条一条翻译到新的机器
  2. 从编译器出发,修改编译器中的代码生成器,为新计算机生成代码。

编译器编译任何Lisp程序是什么意思???
去编译编译器本身是什么意思???然后在新的机器上运行这一编译结果???去编译其他的Lisp程序???
去编译4.1节里的一个解释器,生成一个可以在新机器上运行的解释器???

求值器所用的堆栈操作??
计算所用的编译后代码所用的堆栈操作??
阶乘计算n!时,求值器所需的压栈次数和最大堆栈深度??
手工打造的控制器代码??
程序员可以控制在编译代码中错误检查的范围和种类??
C和C++的编译器通常都不将错误检查代码加入到运行代码里,以便使程序尽可能快速。这样的结果,实际将显示提供错误检查的问题交给程序员处理??
无论编译策略还是解释策略,都需要为新机器实现存储分配,输入输出,及求值器和编译器作出的基本操作。也可在Lisp程序中写出他们,然后新机器中编译它们??
内核其实很小,就是废料收集和实际的基本机器操作??
请在C/C++里开发一个初步的scheme实现,采用的方法是5.4节的显式控制求值器翻译到C/C++,为运行这一例程,需要提供适当的存储分配例程和其他运行支持??
编译4.1节的元循环求值器,生成一个用C写出的scheme解释器??
将编译得到的代码装入求值器??
compile-and-go,它能编译一个scheme表达式,将目标代码装入这部求值器机器,并启动该机器??

(compile-and-go )

盖茨是将别人把basic语言移植到windows平台上的语言继续开发

总部的业务:

  1. 做板卡
  2. 做通信组件
  3. 做加密机

业务单子:
模拟测试

内网ip一直不对,知道把子网掩码从255.255.0.0改成255.255.255.0就可以了,为什么??

求值过程中,最重要的就是一个过程调用其他过程以及将值返回调用者的机制的细节,通过简单的寄存器观察这一求值过程??

你可能感兴趣的:(少林寺一阳指(设计思想),SICP,计算机里的神灵)