2017-02-11 49 views
1

在球拍有可能定義一個程序和常數另一程序的內部,例如是這樣的:球拍是多次運行過程中的定義形式?

(define (a a-list) 
    (define something 10) 
    (display a-list) 
    (cond 
    [(empty? a-list) (display "done")] 
    [else 
     (display a-list) (newline) 
     (a (rest a-list))])) 

打印列表,然後拿走第一元件,然後再依此類推,直到打印列表的該列表是空的。

在示例過程中,值something定義爲10,無論出於何種原因。當程序遞歸時,Racket是否再次定義該值,還是足夠智能地注意到,該定義不會改變?

此外,它可能會在先前調用的過程的堆棧空間上,如果未優化,並且每遞歸步驟會消耗更多的內存,具體取決於something的定義。例如,讓一個列表中有一百萬個數字,但絕不會更改數字。顯然,如果這個定義中的東西依賴於作爲參數給出的列表,那麼它不能簡單地被優化。

如果沒有優化,在遞歸函數中不要有太多的define表單,或者只有那些佔用空間很小的表單?如果將它們放在程序之外,即使只有一個程序使用它們,也可以通過其他程序訪問它們。

回答

1

define表達式在每次調用該過程時進行評估。考慮這個例子:如果你想有一個過程內的值只進行一次(在創建過程本身)評估

(define (test1) 
    (define x (begin (display "Hello from test1 ") 10)) 
    x) 

(test1) 
=> Hello from test1 10 
(test1) 
=> Hello from test1 10 
(test1) 
=> Hello from test1 10 

,你可以把它在程序之外的範圍,但它仍然會訪問因爲lambda在其詞彙環境中定義了一個closure

(define test2 
    (let ((x (begin (display "Hello from test2") 20))) 
    (lambda() x))) 

=> Hello from test2 
(test2) 
=> 20 
(test2) 
=> 20 
(test2) 
=> 20 
+0

我不明白第一個例子。當然,當我調用這個過程時,它會打印'x'的值。我更想知道,如果在幕後進行優化,避免每次都定義「x」的值,因爲每次都是一樣的。 關於如何使用閉包實現它的建議似乎很棒,但如果沒有對程序中的不變定義進行優化(也許一般?)。 也許我應該問一些像_「球拍的JIT優化程序中不變值的定義嗎?」_ – Zelphir

+1

你不明白 - 是的,它會打印'x',但它也會打印出每次顯示部分。定義必須每次都進行評估,這是不可優化的。 –

+0

現在我明白了!謝謝!我不明白的是,爲什麼它會完全不可優化,無論它是什麼樣的定義。我的意思是像'(定義一個10)'和其他不變的值定義。 所以,我想這將是一個很好的做法,使用你在第二個例子中使用的方式,以避免多次評估相同的不變的東西? – Zelphir