现在开始学习《计算机程序的构造和解释》(SICP)。
1.程序设计的基本元素:
三种机制:
1.基本表达式:语言所关心的个体
2.组合的方法:从简单的东西出发构造复合的元素
3.抽象的方法:为符合对象命名,并将它当作单元去操作
两类要素:
1.过程:有关操作数据的规则描述
2.数据:被操作的基本单位
2.基本表达式
Scheme中的最简单的组合式:
(+ 3 1)
组合式:用一对括号将表达式括起来,表示一个过程
Scheme用的是前缀表示的方法,其优点就是可以表示带有任意实参的过程:
(+ 1 2 3 4 6)
3.命名
Scheme使用define关键字来命名一个计算过程,将这个计算过程定义为一个变量。
例如计算圆 的面积:
(define pi 3.14)
(define r 2)
(define space (* pi (* r r)))
space
4.过程定义
LISP中定义过程的一般形式:
(define (<name> <formal parameters>) <body>)
例如一下定义了一个平方的过程:
(define (square x) (* x x))
上表创建了一个复合过程,它还可以被用来构建其他的过程:
(define (sum-of-square x y) (+ (squre x) (squre y)) )
一个程序设计语言中必然包括:
1.数和算术运算是基本的数据和过程
2.组合式的嵌套提供了一种组织起多个操作的方法
3.定义是一种受限的抽象手段,它为名字关联相应的值
5.条件表达式和谓词
Scheme中使用cond来处理多分支的情况:
(define (abs x)
(cond
((> x 0) x)
((= x 0) 0)
((< x 0) (- x))))
这里使用cond来求得x的绝对值,由此可见cond条件表达式的基本形式:
(cond (<p1>,<e1>)
(<p2>,<e2>)
(<p3>,<e3>)
...
(<pn>,<en>)
)
cond后面的子句是一个表达式对偶,其中第一个表达式是谓词
同样,我们也可以加入else符号,类似于default的作用,将abs函数写成:
(define (abs x)
(cond ((< x 0) (- x))
(else x)))
注意else要写在和cond关键字一个括号内
另外,作为二值的条件分支,可以使用if子句:
(if <predicate> <consequent> <alternative>)
predicate 首先求值,如果得到真值,则计算consequent 的内容,否则计算alternative 中的内容。
所以abs函数可构造成if形式:
(define (abs x)
(if (< x 0) ;<predicate>
(- x) ; <consequent>
x)) ;<alternative>
6.实例介绍:牛顿法求平方根
下面先给出代码:
(define (square x)(* x x))
(define (abs x) ;条件if
(cond
((> x 0) x)
((= x 0) 0)
((< x 0) (- x))))
(define (enough iter x) ;判断所迭代的数是否满足iter平方与x的差小于 0.01
(< (abs(- (square iter) x)) 0.01)
)
(define (average x y) ;计算传入的两个数的平均值
(/ (+ x y) 2)
)
(define (improve iter x) ;根据迭代的数和原数获得一个更加接近平方根的数
(average (/ x iter) iter) ;先将原数x除以iter,然后求得该计算值与iter的平均值
)
(define (sqrt-iter iter x)
(if(enough iter x) ;调用enough判断是否满足差足够小,满足则返回该迭代值
iter
(sqrt-iter (improve iter x) x))) ;否则使用递归的形式再次计算
(define (sqrt x)
(sqrt-iter 1.0 x) ;隐去sqrt-iter的计算细节,形成一个黑箱,以1为起始迭代数字
)
(sqrt 5)
分析sqrt的计算过程,可以获得一个过程分解:
我们可以看到整个原问题分解到子问题的过程,同时可以看到过程的定义将实现的细节隐藏了起来,由此形成一个黑箱,调用者不必了解其中实现的细节。
现在我们可以着手将过程局部化:
(define (square x)(* x x))
(define (abs x) ;条件if
(cond
((> x 0) x)
((= x 0) 0)
((< x 0) (- x))))
(define (average x y) ;计算传入的两个数的平均值
(/ (+ x y) 2)
)
(define (sqrt x)
(
(define (enough iter)
(< (abs(- (square iter) x)) 0.01))
(define (improve iter)
(average (/ x iter) iter)
)
(define (sqrt-iter iter)
(if(enough iter)
iter
(sqrt-iter (improve iter))))
(sqrt-iter 1.0)
))
这样的嵌套定义称为块结构,同样由于局部化,我们的x也不必作为参数传入,x就是块内部的自由变量,这种方式称为词法作用域
块结构的设计思想可以做到函数直接分离互不影响,依赖,将子问题形成黑箱用于构建大的问题。