您的位置:首页 > 其它

SICP 习题 (2.6) 解题总结:丘奇计数

2014-09-29 00:33 204 查看
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就容易定义了,就是定义和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))
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: