SICP 1.1节的标题是《The Elements of Programming》,分为如下几个小节,重点在于加粗的内容。

  1. Expressions
  2. Naming and the Environment
  3. Evaluating Combinations
  4. Compound Procedures
  5. The Substitution Model for Procedure Application
  6. Conditional Expressions and Predicates
  7. Example: Square Roots by Newton’s Method
  8. Procedures as Black-Box Abstractions

注:第二小节Naming and the Enviroment在编程语言设计中是单独的一部分内容,未来在些PLP的读书笔记时可能会涉及到,这一小节在SICP中着墨不多

1.1.3 Evaluating Combinations

Expressions such as these, formed by delimiting a list of expressions within parentheses in order to denote procedure application, are called combinations.

这一小节介绍了如何evaluate表达式组合,关于编程中的组合是什么意思见编程语言中的「组合性」是什么意思?。表达式组合最直观的理解就是如何一系列表达式的组合,如下scheme代码所示,就是用来求解22+322^2 + 3^222+32的值。

(+ (* 2 2) (* 3 3))

上面这个表达式就是由三个表达式组合而成的,如下图所示,由两个乘法(* 2 2)(* 3 3)以及加法(+ (* 2 2) (* 3 3))组成。

这个和数学中的函数非常相似,例如我们定义两个数学函数,f(x,y)=x+yf(x, y) = x + yf(x,y)=x+y和g(x)=x∗xg(x) = x * xg(x)=x∗x,那么上面的计算就类似于求f(g(2),g(3))f(g(2), g(3))f(g(2),g(3))的结果。推荐一个比较方便的画数学函数图形的网站,我们将这两个函数放入其中,计算结果会是13。需要注意的是数学函数其实更接近于procedure的概念,而表达式组合,很简单,其实就是数学运算中的(2∗2)+(3∗3)(2 * 2) + (3 * 3)(2∗2)+(3∗3)。

注:到后面我们会发现函数式编程最终来源于邱奇的lambda演算,而命令式编程来源于图灵的图灵机,两者的计算能力等价的

对于表达式组合的求值,SICP给出了如下两个步骤的计算方法:

  • Evaluate the subexpressions of the combination.
  • Apply the procedure that is the value of the leftmost subexpression (the operator) to the arguments that are the values of the other subexpressions (the operands).

首先求解子表达式,然后将子表达式的值代入运算符,求得结果。对于f(g(2),g(3))f(g(2), g(3))f(g(2),g(3))来说,就是先计算g(2)g(2)g(2)和g(3)g(3)g(3)的值,也就是4和9,最终再求解f(4,9)f(4,9)f(4,9)。这个过程是递归进行的,也就是子表达式可能还有子表达式。例如求解g(g(2))g(g(2))g(g(2)),就是先求得g(2)g(2)g(2)

这一小节还提供了define的概念,define的概念可以理解为数学中定义函数的操作,例如下面的代码就类似于数学中的f(x)=9f(x)=9f(x)=9。

(define x 9)

1.1.4 Compound Procedures

当我们先按照数学函数的方式理解函数编程以后,一些东西就比较好理解了。

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

对于上面给出的示例代码,我们就可以使用数学中的函数进行理解,如下图所示,s(x)s(x)s(x)对应于square,f(x,y)f(x, y)f(x,y)对应于sum-of-square,而g(x)g(x)g(x)对应于f,而f(5)也能轻易的算出来为136。

1.1.5 The substitution Model for Procedure Application

这一小节主要介绍了我们如何求解procedure,首先介绍了substitution model,替换模型的核心如下,将过程体重的形参由实参值代替,也就是替换名字的由来。

To apply a compound procedure to arguments, evaluate the body of the procedure with each formal parameter replaced by the corresponding argument.

经过这一步骤以后,就可以转化为求表达式组合的问题,这一过程是递归的,表达式组合中可能也由procedure的求解,此时仍然需要做替换。

(define (square x) (* x x))
(define (sum-of-square x y) (+ (square x) (square y)))
(define (f a)(sum-of-squares (+ a 1) (* a 2)))
(f 5)

对于上述代码,要求f(5)f(5)f(5),首先进行替换,得到如下代码:

(sum-of-squares (+ 5 1) (* 5 2))

此时就是表达式组合问题,先求解子表达式值,如下代码:

(sum-of-squares 6 10)

此时又需要进行替换,将sum-of-squares中的形参由实参值代替,如下所示:

(+ (square 6) (square 10))

这种方式就称之为Applicative Order的求解,也就是

the interpreter first evaluates the operator and operands and then applies the resulting procedure to the resulting arguments.

我们使用前面提到的函数g(x)g(x)g(x)来说明Applicative Order和Normal Order的区别。

Applicative Order Normal Order
f(5+1,5∗2)f(5 + 1, 5 * 2)f(5+1,5∗2) f(5+1,5∗2)f(5 + 1, 5 * 2)f(5+1,5∗2)
f(6,10)f(6, 10)f(6,10) f(5+1,5∗2)f(5 + 1, 5 * 2)f(5+1,5∗2)
(s(6)+s(10))(s(6) + s(10))(s(6)+s(10)) (s(5+1)+s(5∗2))(s(5 + 1) + s (5 * 2))(s(5+1)+s(5∗2))
((6∗6)+(10∗10))((6 * 6) + (10 * 10))((6∗6)+(10∗10)) ((5+1)∗(5+1)+(5∗2)∗(5∗2))((5+1) * (5 + 1) + ( 5 * 2) * (5 * 2))((5+1)∗(5+1)+(5∗2)∗(5∗2))
(36+100)(36 + 100)(36+100) (6∗6+10∗10)(6 * 6 + 10 * 10)(6∗6+10∗10)
136136136 136136136

从上面我们可以看到Applicative Order比Normal Order要高效,这也是scheme采用Applicative Order的原因。

习题

Exercise 1.5

由于scheme采用的是Applicative Order,所以下面的代码永远也不会结束,基于substitution model一直在使用(p)替换(p)。但是采用Normal Order就不会出现这样的问题。

(define (p) (p)) (define (test x y)(if (= x 0) 0 y))(test 0 (p))

Exercise 1.6

类似于Exercise 1.5,下面的代码永远也不会终止。

(define (new-if predicate then-clause else-clause) (cond (predicate then-clause)(else else-clause)))(define (sqrt-iter guess x) (new-if (good-enough? guess x)guess(sqrt-iter (improve guess x) x)))

因为new-if是procedure,按照Applicative Order,首先会evaluate argument,例如我们尝试将(sqrt-iter guess x)展开得到下面的代码,good-enough能够evaluate直接得到结果,guess也可以直接得到结果,而sqrt-iter会继续evaluate new-if,所以scheme解释器在处理这一段代码时出现了没有终止条件的递归,最终会爆栈。

(new-if (good-enough? guess) guess (sqrt-iter(improve guess x) x))^             ^                     ^predicate      then-clause          else-clause

Exercise 1.7

这个问题比较tricky,good-enough?在处理很小的数值时不够精确可以理解,因为小数的平方会更小,所以此时将判断条件附加到平方结果上效果不是很好,例如我们使用0.001来作为判断标准,例如0.0012=0.000010.001^2 = 0.000010.0012=0.00001,0.0022=0.000040.002^2 = 0.000040.0022=0.00004。而对于特别大的数据,请访问 https://sukritkalra94.wordpress.com/2014/05/26/sicp-exercise-1-7-problems-with-good-enough/ 。

This is because floats have a fixed precision. After a certain point, the guesses are unable to guess the square root of a number within 0.001 of the answer. At that point, they alternate between the two guesses, both of whose squares are more than 0.001 away from the argument.

Exercise 1.8

(define (good-enough? old-guess new-guess)(< (abs (- old-guess new-guess)) 0.001))(define (improve guess x)(/ (+ (/ x (* guess guess))(* 2 guess))3))(define (cube-iter guess x)(if (good-enough? guess (improve guess x))guess(cube-iter (improve guess x) x)
))(define (cube-root x)(cube-iter 1.0 x))(cube-root 10000000000)

SICP Section 1.1相关推荐

  1. html中section与div,如何在html中的section标签内包含div标签

    我正在制作一个完整版块的页面网站,如this.每个页面都有自己的标签.目前我的网页有4个部分(呈现不同的背景颜色).如何在html中的section标签内包含div标签 我的第一部分有一个容器div, ...

  2. LATEX 在section层级目录上也加上虚线

    只添加\tableofcontent会导致section层级目录上没有虚线 可以在tex文件一开始先加上下面这句话: \titlecontents{section}[0pt]{\addvspace{5 ...

  3. HTML5新元素section和article的区别详解

    HTML5带出了一系列新元素,并且将在未来被广泛应用.然而,有一些元素在使用时易被混淆,包括以下两个新元素:<article>和<section>. 在问答网站经常可以看到别人 ...

  4. (转).net webconfig使用IConfigurationSectionHandler自定section

    自定义配置结构 (使用IConfigurationSectionHandler)  假设有以下的配置信息,其在MyInfo可以重复许多次,那么应如何读取配置呢?这时就要使用自定义的配置程序了. < ...

  5. 【PHPWord】页面Section

    require_once 'PHPWord.php';$PHPWord = new PHPWord();//默认页面 $section = $PHPWord->createSection(arr ...

  6. 洛谷P1182 数列分段Section II 二分答案

    洛谷P1182 数列分段Section II 二分答案 题意:将 n 个 数 分为 m段 求一种方案,使这m段中最大的和 最小 额..可能有点拗口,其实就是说每一种方案,都有对应的 每段和的最大值, ...

  7. ConfigParser MissingSectionHeaderError: File contains no section headers.

    今天使用ConfigParser解析一个ini文件,报出如下错误: config.read(logFile)File "C:\Python26\lib\ConfigParser.py&quo ...

  8. T100 section已经修改过

    2019独角兽企业重金招聘Python工程师标准>>> T100的开发会碰到没有勾选修改程序框架,程序咨询显示已经被修改过 原因是: 上传签入之后我们再签出的时候就会有section ...

  9. 汇编中的.section命令及汇编语言程序都至少声明的3个段

    汇编语言中最重要的命令之一是.section命令.这个命令定义内存段,汇编语言程序在其中定义元素.所有汇编语言程序都至少具有3个必须声明的段落: ·数据段 ·bss段 ·文本段 数据段用于声明为程序存 ...

最新文章

  1. 精品软件 推荐 硬盘物理序列号修改专家
  2. 波形的转换与信号处理
  3. react实战项目_前端学习路线图--从网页设计到项目开发
  4. inotify+rsync实时同步服务部署
  5. 《乌合之众》读书笔记(part5)--名望的特性就是阻止我们看到事物的原本面目,彻底麻痹我们的判断力
  6. Ajax.net实现的动态输入项
  7. MIP开发常见问题解答
  8. win7安装nodejs 高版本不支持 换低版本
  9. @RequestParam @RequestBody @PathVariable 等参数绑定
  10. IP转发引擎的三种核心处理器区别介绍
  11. 工程量计算稿1.54安装教程 v1.54pjb
  12. android中间件开发技术,基于Android的移动应用开发中间件技术研究与实现
  13. SQL数据库置疑恢复
  14. Pytorch 学习笔记--to(device)的用法
  15. FastQC原始安装
  16. 【OBS Studio】脚本自动生成大量场景思考实践
  17. microsoft认证解说
  18. Java中计算处理中文两个字符长度问题解决(中文2个字符,英文1个字符)
  19. 35岁的程序员:第43章,职级评定
  20. 单电源运放和双电源运放及其供电方式选择与转换的注意事项

热门文章

  1. stm32两轮平衡小车项目详解
  2. Mac下使用Xcode的freopen读取输入输出
  3. c java python sql是什么意思_SQL、Java、Python、C++ 是当今最顶级的技术?
  4. RabbitMQ部署安装
  5. 【一本通评测 1373】【堆】【贪心】鱼塘钓鱼
  6. Windows10/11 缩放与布局自定义
  7. 台式计算机的美图,为什么我在台式电脑上看图片,图片色彩很饱和很鲜艳,而笔记本上看的图片有点暗淡呢...
  8. 牛血清白蛋白修饰牛红细胞超氧化物歧化酶SOD/叶酸偶联2-ME白蛋白纳米粒的制备
  9. QT 视频窗口 OSD 使用详解
  10. 根据入库时间和出库时间计算库存