2010-10-13 13 views
8

Czytam następującą sekcję SICPPytanie o SICP chpt 4.1: W jaki sposób (analysis expr) pomaga przyspieszyć eval?

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

Zgodnie z tekstem, co następuje transformacja eval poprawi oferuje poprawę wydajności, ponieważ wyraz, który pobiera ocenianego wielokrotnie analizowane będą tylko raz ?

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

Oto analyze funkcja podana w książce:

(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))))) 

Nie rozumiem, dlaczego książka mówi, że analyze będzie działał tylko jeden raz. Czy ciało eval, czyli , nie mówi, że za każdym razem, gdy jest wywoływane eval, jako jego parametr zostanie wywołana analyze z exp? Oznaczałoby to, że analyze będzie wywoływane za każdym razem, gdy zostanie wywołane eval.

Co jest nie tak z moim zrozumieniem? Byłbym wdzięczny za wszelkie opinie, dzięki!

Odpowiedz

5

Rzeczywiście, za każdym razem, gdy wywołujesz eval z kodem programu jako parametrem, wywoływacz syntaktyczny zostanie wywołany. Jednakże, gdy funkcja w tym kodzie wywołuje inną funkcję w tym kodzie (lub w najprostszym przypadku wywołuje się przez rekursję), wewnętrzna apply otrzyma analizowane wyrażenie (które jest w końcu funkcją lambda) jako argument , a nie blob kodu, który musiałby być ponownie przeanalizowany syntaktycznie, aby mógł zostać wykonany.

5

Odpowiedź Gintautasa jest prawidłowa, ale może przykład jest w porządku. Załóżmy, że opracowaliśmy dialekt Scheme, który ma konstrukcję pętli, która zawiera oczywistą semantykę. Teraz, kiedy zadzwonić naiwne eval ocenić pętlę, która biegnie dziesięć razy

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

to będzie analizować ciała pętli dziesięć razy. W wersji eval, która oddziela analizę od oceny, treść pętli jest analyze d raz, a następnie oceniana dziesięć razy.

Faza analizy zwraca procedurę, która może być lub nie być szybka w programie tłumaczącym Schemat. Jednak może on wykonywać wszystkie rodzaje optymalizacji (analiza martwego kodu, JIT compilation na kod maszynowy itp.).

2

odpowiedzi larsmans jest bardzo dobra.

Jako odpowiedź uzupełniającą, można również wyświetlić analyze(environ) jako curried postaci eval(expr, environ), gdzie parametr expr został przekazany przed czasem. W SICP można odczytać kodu przykład takiego:

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

Kiedy widzisz let (([var] [preprocessed stuff])), że jest przerób przechowywane w zamknięciu aż jest ona potrzebna później, kiedy environ jest przekazywana w

.