2015-09-02 14 views
5

ho scoperto che il programma per controllare se lo scoping è lessicale o dinamico è quello indicato di seguito (fonte: http://inst.eecs.berkeley.edu/~cs61a/su10/resources/sp11-Jordy/scope/)programma per controllare se lo scoping è lessicale o dinamico

(define test 
    (let ((scope 'lexical)) 
    (lambda() scope))) 

(let ((scope 'dynamic)) 
    (test)) 

Ma come è possibile questo lavoro? Questo dovrebbe sempre essere "lessicale" (indipendentemente dal fatto che l'ambito sia lessicale o dinamico) giusto? poiché nello scope locale del corpo del primo 'let', lo scope viene sempre definito come 'lessicale'. Correggetemi se ho torto

risposta

6

Lo schema utilizza lo scope lessicale, quindi ovviamente il codice restituisce sempre lexical. Tuttavia, in un sistema Lisp che utilizza l'ambito dinamico, scope sarebbe effettivamente dynamic all'interno dell'espressione (let ((scope 'dynamic)) ...) ....

Per comprendere ciò, è necessario comprendere come viene implementato lo scoping dinamico. Pensa a ciascuna variabile come avente una pila di valori. Quindi, quando veniva valutata l'espressione lambda, il valore lexical è stato spostato nello stack di valori scope (tramite let). Quando si esce dal blocco let, il valore viene interrotto. Successivamente, il secondo blocco let inserisce il valore dynamic nello stack di valori scope, che è ciò che viene visualizzato dalla funzione.

Apprezzo molto il the explanation from the Emacs Lisp manual su come i collegamenti dinamici funzionano in termini di stack. Mi ha aiutato a capire veramente il concetto in termini concreti.

+0

Ho compreso i programmi nel collegamento e il concetto di stack spiegato qui. Grazie per le informazioni. Ma quando la funzione di test viene chiamata dal secondo "let", il codice all'interno del blocco di definizione viene eseguito e il blocco di let all'interno della funzione di test deve nuovamente inviare il valore "lessicale allo stack prima dell'esecuzione del blocco lambda, giusto?". .. o qual è il problema nella mia comprensione dell'esecuzione? –

+2

@SubinP Il 'define' non viene eseguito quando si chiama la funzione, la funzione è già definita come' (lambda() scope) '. – molbdnilo

+0

Grazie, è chiaro ora –

6

Il valore di test non è

(let ((scope 'lexical)) 
    (lambda() scope)) 

è solo

(lambda() scope) 

Quando si chiami, (test), il corpo della funzione viene valutata, e si compone solo di

scope 

Con scope lessicale, questo sarebbe il valore nel binding che era in eff ect quando la definizione è stata valutata, ovvero il lessico che include let-binding.

Con ambito dinamico, il binding di scope non viene rilevato finché non viene chiamata la funzione.
In quel momento, il binding a 'lexical è andato da molto tempo - esiste solo durante la definizione di test.

Quando si

(let ((scope 'dynamic)) 
    (test)) 

una nuova associazione viene introdotto nell'ambiente, e questo è il legame che si trova durante la ricerca di scope.

La funzione simile

(define test 
    (lambda() 
     (let ((scope 'whatever)) 
      scope))) 

avrebbe funzionato il modo in cui si suggeriscono - sempre tornare 'whatever - come il legame con 'whatever è a tutti gli effetti durante la valutazione di scope anche in un ambiente dinamico.

Problemi correlati