SICP 習題 (1 41)解題總結

2021-06-21 12:17:03 字數 3380 閱讀 7381

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)解題總結

sicp 習題1.41 看似和周邊的題目沒有關係,突然叫我們去定義乙個叫double的過程,事實上這道題的核心還是高階函式。題目要求我們定義乙個過程double,它以乙個過程作為引數,這個作為引數的過程已經約定是乙個單引數過程。double過程須要返回乙個過程,所返回的過程將傳入的過程應用兩次。舉例...

SICP 習題 1 14 解題總結

sicp 習題 1.14要求計算出過程count change的增長階。count change是書中1.2.2節講解的用於計算零錢找換方案的過程。要解答習題1.14,首先你需要理解count change的工作方式,要理解count change的工作方式,最好是自己去實現一遍count chan...

SICP 習題 1 22 解題總結

sicp 習題 1.22 要求改進題中列舉出來檢查素數的過程,用來求1000,10000,100 000,還有1000 000附近的素數,然後比較求這些素數的時間,看是否符合 n 的複雜度。要完成這道題首先要將題目中列出的過程照抄到你的scheme環境中。因為書中的 使用了 runtime 過程,我...