【SICP归纳】6 副作用与环境模型
虽说叫做副作用显得不太好听,但在Lisp中副作用还是非常重要的。而相对于所有状态都必须显式地操作和传递额外参数的方式,如果引进赋值和将状态隐藏在局部变量中,那么就可以用更加模块化的方式来构造系统。
正如你所知道的,不用任何赋值的程序设计称为函数式程序设计。相反,广泛采用赋值的程序设计称为命令式程序设计。在C等命令式程序设计语言中,我们往往都要仔细考虑变量赋值的顺序,尤其是在循环中,但在函数式程序设计中这类问题根本不会出现。
(define x 1)
(define (add-x y)
(set! x (1+ x))
(+ x y))
(add-x 3)
5
(add-x 3)
6
在这里我们看到同一个表达式却会导致两种不同的结果,而这一切都取决于时间。
我们常用define来定义一个为定义的变量、函数等等,而不用其来做修改的操作。set!则来完成修改这一工作。经常用到的let实际上是一个过程调用的语法糖衣。用define定义一个符号,也就是在当前环境框架里建立一个约束,并赋予这个符号指定的值。
(let ((var1 e1) (var2 e2))
e3)=>
((lambda (var1 var2)
e3)
e1
e2)
在前面的代换模型中,我们是这样求组合式的:
1)求值该组合式的各个子表达式
2)将作为最左子表达式(运算符)的值的那个过程应用于相应的实际参数,所谓实际参数也就是其他子表达式(运算对象)的值。
而在环境模型中,第二步就有所差异了:
1)求值该组合式的各个子表达式
2)将运算符子表达式的值应用于运算对象子表达式的值。
在将一个过程应用于一组实际参数时,将会建立起一个新环境,其中包含了将所有形式参数约束与对应的实际参数的框架,该框架的外围环境就是所用的那个过程的环境。
书中这部分可谓归纳的非常好,过程应用的环境模型的两条规则:
1)将一个过程对象应用于一集实际参数,将构造出一个新框架,其中将过程的形式参数约束到调用时的实际参数,而后在构造起的这一新环境的上下文中求值过程体。这个新框架的外围环境就是作为被应用的那个过程对象的一部分的环境。
2)相对于一个给定环境求值一个lambda表达式,将创建起一个过程对象,这个过程对象是一个序对,由该lambda表达式的正文和一个指向环境的指针组成,这一指针指向的就是创建这个过程对象时的环境。
现在我们已经有能力去使用独立的本地状态和对象模型,也会进行一些比较复杂的编程。我们活在物理世界中,也以物理世界的方式去思考,这正是由这些构成了整个世界。为什么物理学家、天文学家等在寻找系外生命时要以地球的指数为参照,比如说温度、大气、土壤、公转和自转等,因为有些事物是共通的。之前看到过一个老外写的书,当时对软件这个专业还没有多少认识,书也全是理论比较晦涩因此没能看多久,不过记得作者的一个比喻非常好。其认为写一个软件就像设计一座建筑,每部分有组织的组合拼凑在一起。
《计算机程序的构造和解释》虽然已经有了三十多年的历史,却依旧格外而不落伍的原因便是其是在讲解如何去构建一座建筑。它会告诉我们建筑的每个部分都有哪些功能和优缺点,这个柱子该放在哪里撑着,两层楼之间该怎样结合等等。而各自语言就像修建这个建筑的各种材料,比如钢铁和木材等。其并没有太注意去讲解语言的语法,一来这是介绍“建筑材料”的书籍需要做的,二来Lisp的语法也不太繁杂。
在我们的脑海中有对这个世界的认识以及一个不断构建中的模型,当我们在编写软件时,这些模型也即体现于计算机中。我们想要做的无非就是让这两者之间进行通信。这就带来了模块化,如果我们真的相信世界就是由这样的小片段所组成,那么我们也同样可以将这种思想应用于我们所构造的模型中,世界上的这些事物也将能够继承这种模块化设计进入我们的程序之中。
感谢访问,希望对您有所帮助。 欢迎关注或收藏、评论或点赞。
为使本文得到斧正和提问,转载请注明出处:
http://blog.csdn.net/nomasp
版权声明:本文为 NoMasp柯于旺 原创文章,如需转载请联系本人。