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解題完畢。這道題也能夠非常好地幫助同學們理解高階函數,特別是高階函數的嵌套。
SICP 習題 (1.41)解題總結