zoukankan      html  css  js  c++  java
  • SICP 习题 (1.41)解题总结

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


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


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

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

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


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


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


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

    (define (double f)
      (lambda (x) 
        (f (f x)))) 
    

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

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

    最后直接測试

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

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


    为什么呢?


    我们能够一步一步展开


    ;首先将不同的double标号。各自是double1 , double2, double3,这样比較清晰
    (define step1 (((double1 ( double2 double3)) my-inc) 5))
    
    ;然后将(double2 double3)展开:
    (define step2 (((double1 (lambda (x) (double3 (double3 x)))) my-inc) 5))
    
    ;将(lambda (x) (double3 (double3 x))) 命名为lam1:
    (define (lam1 x) (double3 (double3 x)))
    
    ;这样step2就等同于以下的step3:
    (define step3 (((double1 lam1) my-inc) 5))
    
    ;再将(double1 lam1)展开:
    (define step4 (((lambda (x) (lam1 (lam1 x))) my-inc) 5))
    
    ;将my-inc代入step4中得lambda中:
    (define step5 ((lam1 (lam1 my-inc)) 5))
    
    ;将里面的lam1还原回原来的定义:
    (define step6 ((lam1 (double3 (double3 my-inc))) 5))
    
    ;将里面的(double3 my-inc)展开:
    (define step7 ((lam1 (double3 (lambda (x) (my-inc (my-inc x))))) 5))
    
    ; 将step7里的lambda定义为lam2:
    (define (lam2 x) (my-inc (my-inc x)))
    
    。那么step7能够转换为:
    (define step8 ((lam1 (double3 lam2)) 5))
    
    ; 再将step8中的(double3 lam2)展开得到step9:
    (define step9 ((lam1 (lambda (x) (lam2 (lam2)))) 5))
    
    ;将step9中得lambda函数定义为lam3:
    (define (lam3 x) (lam2 (lam2)))
    
    ;那么step9就能够转换成step10这样:
    (define step10 ((lam1 lam3) 5))
    
    ; 将step10中的lam1恢复成原来的定义:
    (define step11 ((double3 (double3 lam3)) 5))
    
    ;将(double3 lam3)展开:
    (define step12 ((double3 (lambda (x) (lam3 (lam3 x)))) 5))
    
    ;将step12中的lambda函数命名为lam4:
    (define (lam4 x) (lam3 (lam3 x)))
    
    ;则step12能够表示成step13这样:
    (define step13 ((double3 lam4) 5))
    
    ;将(double3 lam4)展开:
    (define step14 ((lambda (x) (lam4 (lam4 x))) 5))
    
    ;将5代入step14中的lambda过程中:
    (define step15 (lam4 (lam4 5)))
    
    ;将lam4还原回原始定义:
    (define step16 (lam3 (lam3 (lam3 (lam3 5)))))
    
    ;将lam3还原回原始定义:
    (define step17 (lam2 (lam2 (lam2 (lam2 (lam2 (lam2 (lam2 (lam2 5)))))))))
    
    ;将lam2还原回原始定义:
    (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)))))))))))))))))
    
    。结果就是21了:
    (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解题完毕。这道题也能够非常好地帮助同学们理解高阶函数,特别是高阶函数的嵌套。


  • 相关阅读:
    GIT初探
    IIS7添加虚拟目录映射另一台服务器的共享文件夹
    The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF
    asp.net编码解码的两篇文章
    生成网站时提示 已预编译此应用程序
    错误 1 无法将程序集“NBear.Data.dll”复制到文件“D: ewbpmpmSureBpmBinNBear.Data.dll”。无法将“D: ewbpmpmSureSoft.WebServiceBaseLibinDebugNBear.Data.dll”添加到网站。 无法添加文件“BinNBear.Data.dll”。 拒绝访问。 D:..
    从Script到Code Blocks、Code Behind到MVC、MVP、MVVM(转载)
    HTML form表单的默认提交方式
    webapp检测手机运动方向,可实现手机摇一摇功能的触发
    手机/P各种提示框整合,纯js实现,比前端大多数框架的提示消息更好用
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7069216.html
Copyright © 2011-2022 走看看