SICP 习题 (2.6) 解题总结:丘奇计数
SICP 习题 2.6 讲的是丘奇计数,是习题2.4 和 2.5的延续。
这里大师们想提醒我们思考的是“数”究竟是什么,在计算机系统里能够怎样实现“数”。准备好開始脑洞大开吧:
题目先讲到以下的定义,首先是0的定义:
(define zero (lambda (f) (lambda (x) x)))
然后是操作+ 1的定义:
(define (add-1 n)
(lambda (f) (lambda (x) (f ((n f) x)))))
接着题目就要求我们依据以上的过程開始定义数 1 和 2, 然后再定义主要的+操作。
说实话,第一次看到这道题的时候我对着上面三行代码看了半天也是稀里糊涂的。搞不清楚这种代码和数字有什么关系。
当中一个关键是我总是希望zero能够被输出为0。而(add-1 zero)过程会输出一个数字1。
有谁说过仅仅有符号0才代表数字“零”呢?一个空空的口袋不能代表“零”吗? 又有谁说过仅仅有符号1才代表数字“壹”呢?在苍茫大地上孤独行走的我不能代表“壹”吗?
把你的脑洞开到这个程度差点儿相同你就能够理解丘奇计数了。
丘奇计数的基本想法就是通过调用0次函数来表示0,通过调用1次函数来表示1,以此类推。。
。
所以。这里的zero事实上是一个lambda过程,该过程接受还有一个过程作为參数,只是对该过程调用0次,什么叫调用0次呢,就是传人什么參数就返回什么參数喽。
相应的,(add-1 n)过程也是返回一个lambda过程。该过程接受还有一个过程作为參数,对该过程调用n+1次。
这样理解的话,1和2就easy定义了,就是定义和zero相似的lambda过程,只是这次各自是调用1次和2次传入的过程。代码例如以下:
(define one
(lambda (f) (lambda (x) (f x)))) (define two
(lambda (f) (lambda (x) (f (f x)))))
借着是要考虑怎样实现+的操作,我们知道丘奇计数里的“数”事实上就是调用传入过程的次数。那就比較简单,假设要将两个丘奇计数中的数n和m加起来。事实上就是对传入过程调用(n+m)次。用以下这种简单嵌套就能够实现了:
(define (plus first second)
(lambda (f)
(lambda (x)
((first f) ((second f) x)))))
最后你可能会有疑问,像这种计数有什么意义吗?
事实上这里体现的是更高阶的“数”的理解,我们能够通过简单的办法降阶。我们能够定义以下这样一个接近于无聊的过程:
(define (f x)
(display "*")
)
这个过程仅仅接受一个參数,过程体什么都不做,仅仅是打印一个*号。
由于丘奇计数事实上计算的是过程的调用次数,所以假设我们将以上过程使用在丘奇计数中,就能够通过打印出来的*号直观地感受到丘奇计数中“数”的概念。
比方运行((two f) ‘a)会打印2个*号。
运行((one f) ‘a)会打印1个*号。
很多其它调用例子请參考以下代码:
(define (start-test-2-6) (display "going to display 1:")(newline)
((one f) 'a)(newline)
(display "going to display 2:")(newline)
((two f) 'a) (newline)
(display "going to display 1+2:")(newline)
(((plus one two) f) 'a)
(newline)
(display "going to display 1+2+2")(newline)
(((plus (plus one two) two) f) 'a)
(newline) (display "end.") (newline))
SICP 习题 (2.6) 解题总结:丘奇计数的更多相关文章
- SICP 习题 (1.13) 解题总结
SICP习题1.13要求证明Fib(n)是最接近φn/√5 的整数,其中φ=(1+√5)/2 .题目还有一个提示,提示解题者利用归纳法和斐波那契数的定义证明Fib(n)=(φn - ψn) / √5 ...
- SICP 习题 (1.7) 解题总结
SICP 习题 1.7 是对正文1.1.7节中的牛顿法求平方根的改进,改进部分是good-enough?过程. 原来的good-enough?是判断x和guess平方的差值是否小于0.001,这个过程 ...
- SICP 习题 (1.14)解题总结
SICP 习题 1.14要求计算出过程count-change的增长阶.count-change是书中1.2.2节讲解的用于计算零钱找换方案的过程. 要解答习题1.14,首先你需要理解count-ch ...
- SICP 习题 (1.8) 解题总结
SICP 习题1.8需要我们做的是按照牛顿法求平方根的方法做一个求立方根的过程. 所以说书中讲牛顿法求平方根的内容还是要好好理解,不然后面这几道题做起来就比较困难. 反过来,如果理解了牛顿法求平方根的 ...
- SICP 习题 (1.9) 解题总结
SICP 习题 1.9 开始针对“迭代计算过程”和“递归计算过程”,有关迭代计算过程和递归计算过程的内容在书中的1.2.1节有详细讨论,要完成习题1.9,必须完全吃透1.2.1节的内容,不然的话,即使 ...
- SICP 习题 (1.10)解题总结
SICP 习题 1.10 讲的是一个叫“Akermann函数”的东西,去百度查可以查到对应的中文翻译,叫“阿克曼函数”. 就像前面的解题总结中提到的,我是一个数学恐惧者,看着稍微复杂一点的什么函数我就 ...
- SICP 习题 (2.7) 解题总结 : 定义区间数据结构
SICP 习题 2.7 開始属于扩展练习,能够考虑不做,对后面的学习没什么影响.只是,假设上面的使用过程表示序对,还有丘奇计数你都能够理解的话,完毕这些扩展练习事实上没什么问题. 习题2.7是要求我们 ...
- SICP 习题 (1.41)解题总结
SICP 习题1.41 看似和周边的题目没有关系,突然叫我们去定义一个叫double的过程,事实上这道题的核心还是高阶函数. 题目要求我们定义一个过程double,它以一个过程作为參数,这个作为參数的 ...
- SICP 习题 (2.10)解题总结: 区间除法中除于零的问题
SICP 习题 2.10 要求我们处理区间除法运算中除于零的问题. 题中讲到一个专业程序猿Ben Bitdiddle看了Alyssa的工作后提出了除于零的问题,大家留意一下这个叫Ben的人,后面会不断 ...
随机推荐
- Android漫游记(4)---.so文件动态调试一例
Android平台的动态调试一直以来是个困扰我等Coder的头疼问题,特别是对于本地的动态调试支持.能够说是"弱智"级别的,不知道Google的新版NDK和新出的Android S ...
- Python笔记之面向对象
1.类和对象 #create a class class fruit: def say(self): print "hello, python" if __name__ == &q ...
- (转载)Jvm工作原理学习笔记
一. JVM的生命周期 1. JVM实例相应了一个独立执行的java程序它是进程级别 a) 启动.启动一个Java程序时.一个JVM实例就产生了.不论什么一个拥有publ ...
- IOS开发之UIView总结
如果想调用某个类的某个方法可以写成这样,这个方法来自NSObject类 performSelector: performSelector:withObject: performSelector:wit ...
- ViewState的用法
学习标签: ViewState 本文导读:在web窗体控件设置为runat = "server",这个控件会被附加一个隐藏的属性_ViewState,_ViewState存放了所有 ...
- Qt 打包发布 不能动态打开图片显示问题
刚写完一个图片标注工具, 发现在我电脑可以实时打开照片显示出来,在他人的电脑上就不可以. 原来Qt默认只识别png 具体解决方案: 原地址:http://blog.csdn.net/goodlixue ...
- Qt显示调用vs中的dll
网上看到很多文章写调用vc的dll,但我尝试了总是出问题,下面结合参考别人的文章,实现了Qt显示调用vs中c接口的dll. 具体直接上代码: vs中的代码: TMax.h: #ifdef TMAX # ...
- CentOS6.4 安装 Oracle11g
1.硬件要求检查: 1.1 内存要求: 内存大于1G(使用虚拟机安装时内存要稍微大一些,否则安装检查不通过) #cat /proc/meminfo //查看内存大小 1.2 交换分区要求: 交换分区是 ...
- 基于visual Studio2013解决C语言竞赛题之1076放鞭炮
题目 解决代码及点评 /************************************************************************/ /* ...
- 一百多道.NET面试题!
1.a=10,b=15,在不用第三方变量的前提下,把a,b的值互换 方法一: a=a+b; b=a-b; a=a-b; 方法二: a^=b^(b^=a^b); 2.已知数组int[] max= ...