SICP 习题1.41 看似和周边的题目没有关系,突然叫我们去定义一个叫double的过程,事实上这道题的核心还是高阶函数。

题目要求我们定义一个过程double,它以一个过程作为參数,这个作为參数的过程已经约定是一个单參数过程。double过程须要返回一个过程,所返回的过程将传入的过程应用两次。

举例说。假设我们有个过程叫(扇耳光 贱人)。调用这个过程会扇贱人一个耳光。

那么(double 扇耳光)会返回还有一个过程。这个过程没有名字,我们暂且叫他“扇俩耳光”吧,调用(扇俩耳光 贱人)就会扇贱人两个耳光了。

也就是说((double 扇耳光) 贱人)这种调用会扇贱人两个耳光。

好,题目问我们(((double ( double double)) inc) 5)的结果是什么,当中inc方法会给传入參数加1.

要完毕这道题,先看看double怎样定义吧。

全然依照题目意思,定义的double例如以下:

  1. (define (double f)
  2. (lambda (x)
  3. (f (f x))))

为了測试,我定义了一个我自己的inc过程

  1. (define (my-inc x)
  2. (+ x 1))

最后直接測试

  1. (define test-it (((double ( double double)) my-inc) 5))

结果是21,也就是5+16,就是做了16次加一的操作。

为什么呢?

我们能够一步一步展开

  1. ;首先将不同的double标号。各自是double1 , double2, double3,这样比較清晰
  2. (define step1 (((double1 ( double2 double3)) my-inc) 5))
  3.  
  4. ;然后将(double2 double3)展开:
  5. (define step2 (((double1 (lambda (x) (double3 (double3 x)))) my-inc) 5))
  6.  
  7. ;将(lambda (x) (double3 (double3 x))) 命名为lam1:
  8. (define (lam1 x) (double3 (double3 x)))
  9.  
  10. ;这样step2就等同于以下的step3:
  11. (define step3 (((double1 lam1) my-inc) 5))
  12.  
  13. ;再将(double1 lam1)展开:
  14. (define step4 (((lambda (x) (lam1 (lam1 x))) my-inc) 5))
  15.  
  16. ;将my-inc代入step4中得lambda中:
  17. (define step5 ((lam1 (lam1 my-inc)) 5))
  18.  
  19. ;将里面的lam1还原回原来的定义:
  20. (define step6 ((lam1 (double3 (double3 my-inc))) 5))
  21.  
  22. ;将里面的(double3 my-inc)展开:
  23. (define step7 ((lam1 (double3 (lambda (x) (my-inc (my-inc x))))) 5))
  24.  
  25. ; step7里的lambda定义为lam2:
  26. (define (lam2 x) (my-inc (my-inc x)))
  27.  
  28. 。那么step7能够转换为:
  29. (define step8 ((lam1 (double3 lam2)) 5))
  30.  
  31. ; 再将step8中的(double3 lam2)展开得到step9:
  32. (define step9 ((lam1 (lambda (x) (lam2 (lam2)))) 5))
  33.  
  34. ;将step9中得lambda函数定义为lam3:
  35. (define (lam3 x) (lam2 (lam2)))
  36.  
  37. ;那么step9就能够转换成step10这样:
  38. (define step10 ((lam1 lam3) 5))
  39.  
  40. ; step10中的lam1恢复成原来的定义:
  41. (define step11 ((double3 (double3 lam3)) 5))
  42.  
  43. ;将(double3 lam3)展开:
  44. (define step12 ((double3 (lambda (x) (lam3 (lam3 x)))) 5))
  45.  
  46. ;将step12中的lambda函数命名为lam4:
  47. (define (lam4 x) (lam3 (lam3 x)))
  48.  
  49. ;则step12能够表示成step13这样:
  50. (define step13 ((double3 lam4) 5))
  51.  
  52. ;将(double3 lam4)展开:
  53. (define step14 ((lambda (x) (lam4 (lam4 x))) 5))
  54.  
  55. ;将5代入step14中的lambda过程中:
  56. (define step15 (lam4 (lam4 5)))
  57.  
  58. ;将lam4还原回原始定义:
  59. (define step16 (lam3 (lam3 (lam3 (lam3 5)))))
  60.  
  61. ;将lam3还原回原始定义:
  62. (define step17 (lam2 (lam2 (lam2 (lam2 (lam2 (lam2 (lam2 (lam2 5)))))))))
  63.  
  64. ;将lam2还原回原始定义:
  65. (define step18 (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc (my-inc 5)))))))))))))))))
  66.  
  67. 。结果就是21了:
  68. (define step19 21)

以上的分析过程比較繁琐,只是也比較具体。

假设从抽象一点的层面来看的话,也能够用第二种方法

考察以下方法:

(((double ( double double)) my-inc) 5)

double过程的作用是将不论什么方法嵌套调用两次。

而(double double)就是将double嵌套调用两次。结果就是将不论什么方法嵌套调用4次。

假设有(define four-time (double double))的话,fourtime过程将不论什么方法嵌套调用4次。

进一步看得话(double (double double))相当于(double four-time)。

相当于是(four-time (four-time x))

这里要特别注意,两次four-time的嵌套调用并非4+4次,而是4*4次调用,就是16次调用。

习题1.41解题完毕。这道题也能够非常好地帮助同学们理解高阶函数,特别是高阶函数的嵌套。

SICP 习题 (1.41)解题总结的更多相关文章

  1. SICP 习题 (1.13) 解题总结

    SICP习题1.13要求证明Fib(n)是最接近φn/√5 的整数,其中φ=(1+√5)/2 .题目还有一个提示,提示解题者利用归纳法和斐波那契数的定义证明Fib(n)=(φn - ψn) / √5 ...

  2. SICP 习题 (1.7) 解题总结

    SICP 习题 1.7 是对正文1.1.7节中的牛顿法求平方根的改进,改进部分是good-enough?过程. 原来的good-enough?是判断x和guess平方的差值是否小于0.001,这个过程 ...

  3. SICP 习题 (1.14)解题总结

    SICP 习题 1.14要求计算出过程count-change的增长阶.count-change是书中1.2.2节讲解的用于计算零钱找换方案的过程. 要解答习题1.14,首先你需要理解count-ch ...

  4. SICP 习题 (1.8) 解题总结

    SICP 习题1.8需要我们做的是按照牛顿法求平方根的方法做一个求立方根的过程. 所以说书中讲牛顿法求平方根的内容还是要好好理解,不然后面这几道题做起来就比较困难. 反过来,如果理解了牛顿法求平方根的 ...

  5. SICP 习题 (1.9) 解题总结

    SICP 习题 1.9 开始针对“迭代计算过程”和“递归计算过程”,有关迭代计算过程和递归计算过程的内容在书中的1.2.1节有详细讨论,要完成习题1.9,必须完全吃透1.2.1节的内容,不然的话,即使 ...

  6. SICP 习题 (1.10)解题总结

    SICP 习题 1.10 讲的是一个叫“Akermann函数”的东西,去百度查可以查到对应的中文翻译,叫“阿克曼函数”. 就像前面的解题总结中提到的,我是一个数学恐惧者,看着稍微复杂一点的什么函数我就 ...

  7. SICP 习题 (2.10)解题总结: 区间除法中除于零的问题

    SICP 习题 2.10 要求我们处理区间除法运算中除于零的问题. 题中讲到一个专业程序猿Ben Bitdiddle看了Alyssa的工作后提出了除于零的问题,大家留意一下这个叫Ben的人,后面会不断 ...

  8. SICP 习题 (2.7) 解题总结 : 定义区间数据结构

    SICP 习题 2.7 開始属于扩展练习,能够考虑不做,对后面的学习没什么影响.只是,假设上面的使用过程表示序对,还有丘奇计数你都能够理解的话,完毕这些扩展练习事实上没什么问题. 习题2.7是要求我们 ...

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

    SICP 习题 2.6 讲的是丘奇计数,是习题2.4 和 2.5的延续. 这里大师们想提醒我们思考的是"数"究竟是什么,在计算机系统里能够怎样实现"数".准备好 ...

随机推荐

  1. AWR系列之中的一个——AWR简单介绍

    AWR的全称是Automatic Workload Repository(自己主动负载知识库). 它是通过对照两次快照的方式收集到统计信息.来生成txt或者html页面形式的报告. 通常,通过AWR报 ...

  2. Light OJ 1288 Subsets Forming Perfect Squares 高斯消元求矩阵的秩

    题目来源:Light OJ 1288 Subsets Forming Perfect Squares 题意:给你n个数 选出一些数 他们的乘积是全然平方数 求有多少种方案 思路:每一个数分解因子 每隔 ...

  3. HDFS 文件格式——SequenceFile RCFile

     HDFS块内行存储的例子  HDFS块内列存储的例子  HDFS块内RCFile方式存储的例子

  4. batch normalization学习理解笔记

    batch normalization学习理解笔记 最近在Andrew Ng课程中学到了Batch Normalization相关内容,通过查阅资料和原始paper,基本上弄懂了一些算法的细节部分,现 ...

  5. MyEclipse 安装svn 插件步骤详情

    方法一:在线安装 打开HELP- > MyEclipse Configuration Center.切换到SoftWare标签页. 点击Add Site 打开对话框,在对话框Name输入Svn, ...

  6. php开启CURL支持

    window下安装php_curl支持 1. 找到php.ini 修改extension=php_curl.dll 把前面的分号去掉2. 把 php_curl.dll libeay32.dll ssl ...

  7. linux的chmod,chown命令 详解

    指令名称 : chmod 使用权限 : 所有使用者 使用方式 : chmod [-cfvR] [--help] [--version] mode file... 说明 : Linux/Unix 的档案 ...

  8. python小项目之头像右上角加数字

    pillow介绍 一.Image类的属性:1.Format   2.Mode   3.Size    4.Palette    5.Info 二.类的函数:1.New   2.Open   3.Ble ...

  9. Windows 安装 MySQL8

    MySQL8下载地址:https://dev.mysql.com/downloads/mysql/ 解压到安装目录 新建配置文件my.ini [mysqld]# 设置mysql的安装目录basedir ...

  10. Js基础知识(作用域、特殊函数---自调、回调、作为值的函数)

    15.作用域 概念: 规定变量或函数的可被访问的范围和生命周期 分类: 全局作用域 -就是指当前整个页面环境: 局部作用域(函数作用域) -就是指某个函数内部环境 l 变量的作用域 全局变量 - 定义 ...