【SICP】Primitive elements, combination, abstraction

对于了解所有的语言,首先要了解

  1. Primitive elements 基本元素
  2. Means of combination 如何把这些基本元素组合在一起,组合在一起之后的含义是什么,构建出来更大的对象是什么
  3. Means of abstraction 如何利用基本元素进行封装,如何做使得它们可以像基本元素一样使用,以逐渐构建复杂的东西

Primitive elements & Means of combination

Combination 组合式 格式: (+ 3 17.4 5)

  • operator 运算符
  • operands 运算对象

Lisp 的括号不同于数学的括号

  • 数学中的括号用于分组,有些时候可以省略,多加也只会使得分组更明确
  • Lisp 的括号总是意味着所括之物是另一个组合式,在 apply operators to operands,不能多了也不能少了
❌ (* (5) A)
SchemeError: Cannot call 5

Current Eval Stack:
-------------------------
0: (5)
1: (* (5) A)
❌ * (5) A
PrimitiveProcedure
SchemeError: Cannot call 5

Current Eval Stack:
-------------------------
0: (5)
SchemeError: unknown identifier: A

Current Eval Stack:
-------------------------
0: A
1: (5)

Lisp 的 combination 实际上是一棵将二维结构写作线性字符串的语法树

在线运行 Lisp 地址:https://inst.eecs.berkeley.edu/~cs61a/fa14/assets/interpreter/scheme.html

3
(+ (* 3 5)
   (* 47
      (- 20 6.8))
   12)
3
647.4

Means of abstraction

抽象化一些组合式并给它命名,使得可以将其作为一个元素

不带参数的组合式:

(define A(+ 5 5))
(* A A)
(define B(+ A(* 5 A)))

带参数的组合式:

(define (SQUARE X)(* X X))

用 lambda 方式命名带参数的组合式,对 lisp 来说和上面的没区别,只是 syntactic sugar:

(define SQUARE
    (lambda (X) (* X X)))

define 后面有的时候加括号,有的时候不加
define SQUARE 代表定义的是一个符号 SQUARE,把这个符号定义为一个 lambda

define (SQUARE X) 是定义一个 procedure,这个 procedure 带一个参数是 X
如果 define (A)(* 5 5) 也是可以的,这就是定义一个没有参数的 procedure A
具体的:

(define (A)
  (* 5 5))
A
(A)

A -> (lambda () (* 5 5))
(A) -> 25


(define A
  (* 5 5))
A
(A)

A -> 25
SchemeError: Cannot call 25

Current Eval Stack:
-------------------------
0: (A)

带参数过程的使用:

(SQUARE 1001)
(+ (SQUARE 3) (SQUARE 4))
(SQUARE (SQUARE (SQUARE 1001)))

我们无法分辨内建元素(things are built in)与复合元素(things are compound)的区别,因为复合元素经过了一层抽象封装(abstraction wrapper)

Conditional 的过程:

(define (ABS X)
    (cond ((< X 0)(-X)))

(< X 0) 是谓词 predicate / 条件 condition,return true or false

上述式子等价于

(define (abs x)
    (if (< x 0)
        (- x)
        x))

用以上学的内容写平方根(f(y)=x/y 的不动点)

double sqrt(double x){
    double guess=1;
    while(abs(guess - x/guess)>=0){
        guess=(guess + x/guess)/2;
    }
    return guess;
}

可以看到似乎需要 while,这个上面没有
所以我们用递归来代替

(define (improve guess x)
    (average guess(/ x guess)))

(define (good-enough? guess x)           // good-enough? 整体是一个名称
    (< (abs (- (square guess) x))
        .001))

(define (try guess x)
    (if (good-enough? guess x)           // 如果足够好
        guess                            // 进这里 return guess
        (try (improve guess x) x)))      // 否则进这里

(define (sqrt x)(try 1 x))

(sqrt 2)

可以将 improve,good-enough?和 try 放进 sqrt 中
进行了封装,省去了多余的 x 传递
block-structure

(define (sqrt x)
    (define (improve guess)
        (average guess(/ x guess)))
    (define (good-enough? guess)             // good-enough? 整体是一个名称
        (< (abs (- (square guess) x))
            .001))
    (define (try guess)
        (if (good-enough? guess)           // 如果足够好
            guess                            // 进这里 return guess
            (try (improve guess))))      // 否则进这里
    (try 1))

(sqrt 2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值