2010-10-13 5 views
8

Sto leggendo la seguente sezione di SICPDomanda su SICP chpt 4.1: In che modo (analizza expr) aiuta ad accelerare l'eval?

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

Secondo il testo, la seguente trasformazione di eval migliorerà offre un miglioramento delle prestazioni, in quanto espressione che viene valutata molte volte verranno analizzati solo una volta ?

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

Ecco un analyze funzione data nel libro:

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

Non capisco il motivo per cui il libro dice che analyze verrà eseguito solo una volta. Non è il corpo di,, che è ((analyze exp) env)) sostanzialmente dire che ogni volta che viene chiamato eval, analyze verrà chiamato con exp come parametro? Ciò significherebbe che analyze verrebbe chiamato ogni volta che viene chiamato eval.

Cosa c'è di sbagliato nella mia comprensione? Gradirei qualsiasi feedback, grazie!

risposta

5

In effetti, ogni volta che si chiama eval con codice programma come parametro, verrà richiamato l'analizzatore sintattico. Tuttavia, quando una funzione all'interno di quel codice chiama un'altra funzione all'interno di quel codice (o, nel caso più semplice, si chiama per ricorsione), l'interno apply otterrà l'espressione analizzata (che è alla fine una funzione lambda) come argomento piuttosto che un insieme di codice che dovrebbe essere nuovamente analizzato sintatticamente per essere eseguito.

5

La risposta di Gintautas è corretta, ma forse un esempio è in ordine. Supponiamo di aver sviluppato un dialetto Scheme che sfoggia un costrutto ciclico

(do-n-times n expr) 

con la semantica ovvia. Ora, quando si chiama il ingenuo eval per valutare un ciclo che corre dieci volte

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

allora sarà analizzare il corpo del ciclo dieci volte. Con la versione di eval che separa l'analisi dalla valutazione, il corpo del loop è analyze una volta, quindi valutato dieci volte.

La fase di analisi restituisce una procedura, che può essere o meno veloce nell'interprete Scheme. Tuttavia, potrebbe teoricamente fare tutti i tipi di ottimizzazioni (analisi del codice morto, JIT compilation al codice macchina, ecc.).

2

Le risposte di larsmans sono estremamente buone.

Come risposta complementare, è anche possibile visualizzare analyze(environ) come un tipo al curry di eval(expr, environ) dove il parametro expr è stato inoltrato in anticipo. In SICP, è possibile leggere il codice di esempio come:

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

Quando si vede un let (([var] [preprocessed stuff])), che viene pre-elaborazione verrà conservata in una chiusura fino a quando non è necessaria più tardi, quando è passato in environ

.
Problemi correlati