2011-12-23 56 views
3

我讀了一本書的計劃,它有下面的例子:計劃 - 動態範圍和infinte環

(define map 
    (lambda (f s) 
    (if (null? s) 
     '() 
      (cons (f (car s)) 
       (map f (cdr s))))) 

(map (lambda (s) 
     (set! s '(1 2 3 4)) 
     'hello) 
    '(a b c d)) 

它說,在動態範圍,我們將進入無限循環。但爲什麼?據我瞭解,我們申請後,我們到達與地圖

f = (lambda (s) 
     (set! s '(1 2 3 4)) 
     'hello) 

和s = '(a b c d)。現在,第一次運行時,我們將在(car '(a b c d)適用f

((lambda (s) 
    (set! s '(1 2 3 4)) 
    'hello) 
(car '(a b c d))) 

而現在,它改變a(1 2 3 4)。等等..這裏的循環在哪裏?

+1

這與問題並不完全相關,但對'f'的調用會將'a'改爲''(1 2 3 4)'「是不正確的。 Scheme通過值傳遞函數參數,所以'(set!s)'唯一可以改變的就是當前範圍內變量's'的值。要替換原始列表中的'a',函數必須將整個列表作爲參數並調用'set-car !'。 – 2011-12-23 16:05:51

回答

1

我覺得作者的意思是,後f (car s)執行的s值將是'(1 2 3 4),所以(cdr s)值將是'(2 3 4),所以你會打電話給(map f '(2 3 4))每一次循環往復。

但我不認爲這是動態範圍的準確描述。由於s是拉姆達參數(因此不是自由變量),因此只有該參數應該受set!map函數的s影響。所以應該沒有無限循環 - 無論你是否使用動態範圍。如果我將代碼翻譯成elisp(它是動態範圍的),那麼代碼確實不會導致無限循環。所以我會說你的書是錯誤的,說使用動態範圍會有一個無限循環。

+0

謝謝,但我沒有得到作者想說的。在dynam和c中,地圖中的's'總是變化的。每個地圖的調用都會打開新框架,並且會發生變化。也許他錯了,但我根本沒有想到。謝謝。 – 2011-12-23 16:12:21

+3

至少,這個例子好像是錯的。但是,如果傳遞給'map'的函數是'(lambda(x)(set!s'(1 2 3 4))...',那麼你會*得到一個無限循環,因爲匿名函數會改變屬於'map'範圍的's'這是一個人爲的例子,但它確實顯示了動態範圍如何泄漏實現細節,如局部變量的名稱。 – 2011-12-23 16:18:38