2010-10-13 17 views
8

我讀SICP的以下部分關於SICP chpt 4.1的問題:(分析expr)如何幫助加速eval?

http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-26.html#%_sec_4.1.7

根據課文的eval以下改造將提高提供性能改進,因爲這被評價多次將只進行一次分析表達?

(define (eval exp env) 
    ((analyze exp) env)) 

下面是書中給出的analyze功能:

(define (analyze-if exp) 
(let ((pproc (analyze (if-predicate exp))) 
    (cproc (analyze (if-consequent exp))) 
     (aproc (analyze (if-alternative exp)))) 
    (lambda (env) 
     (if (true? (pproc env)) 
      (cproc env) 
       (aproc env))))) 

我不明白爲什麼書上說analyze將只運行一次。 eval,即((analyze exp) env))基本上說是不是每次調用evalanalyze都會調用exp作爲它的參數?這意味着每調用一次eval就會調用analyze

我的理解有什麼問題?我將不勝感激任何反饋,謝謝!

回答

5

事實上,每次您調用eval並將程序代碼作爲參數時,都會調用語法評估程序。但是,當代碼中的某個函數調用該代碼中的另一個函數時(或者,在最簡單的情況下,它通過遞歸調用它自己),內部的apply將得到分析的表達式(最後是一個lambda函數)作爲參數而不是爲了執行而需要語法分析的代碼塊。

5

Gintautas的回答是正確的,但也許是一個例子。假設你已經開發了一種體育環結構的方言方言

(do-n-times n expr) 

具有明顯的語義。現在,當你調用天真eval評估運行十倍

(eval '(do-n-times 10 (print 'hello))) 

然後將分析循環體十次的循環。使用eval版本將評估與評估分開,循環體爲analyzed一次,然後評估十次。

分析階段返回一個過程,在你的Scheme解釋器中可能不快。然而,可以想像做各種優化(死代碼分析,JIT compilation機器碼等)。

2

larsmans的回答非常好。

作爲一個補充答案,人們還可以將analyze(environ)視爲eval(expr, environ)的一個已被壓縮的格式,其中參數expr已提前通過。在SICP,你可以讀到這樣的例子代碼:

(define (analyze-assignment exp) 
    (let ((var (assignment-variable exp)) 
     (vproc (analyze (assignment-value exp)))) 
    (lambda (env) 
     (set-variable-value! var (vproc env) env) 
     'ok))) 

當你看到一個let (([var] [preprocessed stuff])),即在預處理被存儲在一個封閉直到需要它後,當environ在傳遞