2010-07-09 11 views
14

ho studiato Schema di recente e venire attraverso una funzione che è definita nel seguente modo:Nello Schema lo scopo di (let ((cdr cdr))

(define remove! 
    (let ((null? null?) 
      (cdr cdr) 
      (eq? eq?)) 
    (lambda ... function that uses null?, cdr, eq? ...) 

Qual è lo scopo di null vincolante ? null? o CDR CDR, quando questi sono costruiti in funzioni che sono disponibili in una definizione di funzione, senza un blocco let?

risposta

30

Nel semplice Schema R5RS, non esiste un sistema di moduli: solo il livello superiore thermore, la mentalità è che tutto può essere modificato, così puoi "personalizzare" la lingua come preferisci. Ma senza un sistema modulare questo non funziona bene. Ad esempio, io scrivo

(define (sub1 x) (- x 1)) 

in una libreria che si carica - e ora è possibile ridefinire -:

(define - +) ; either this 
(set! - +) ; or this 

e ora è involontariamente rotto la biblioteca che si basava su sub1 decrementare suo ingresso per uno e di conseguenza le finestre si alzano quando le trascini verso il basso, o qualsiasi altra cosa.

L'unico modo per aggirare questo, che viene utilizzato da diverse biblioteche, è quello di "afferrare" la relativa definizione della funzione di sottrazione, prima che qualcuno possa modificarlo:

(define sub1 (let ((- -)) (lambda (x) (- x 1)))) 

Ora le cose funzionerà "più fine ", poiché non è possibile modificare il significato della mia funzione sub1 modificando -. (Tranne ... chi lo modifica prima di caricare la mia libreria ...)

In ogni caso, a causa di questo (e se si sa che il - è quello originario quando la libreria viene caricata), alcuni compilatori lo rileveranno e vedranno che la chiamata - sarà sempre la funzione di sottrazione effettiva e pertanto invieranno le chiamate ad essa (e inlining una chiamata a - può alla fine risultare in codice assembly per sottrarre due numeri, quindi questo è un grande aumento di velocità). Ma come ho detto nel commento sopra, questo è più casuale della ragione attuale sopra.

Infine, R6RS (e diverse implementazioni regime prima che) ha risolto questo e ha aggiunto un sistema bibliotecario, quindi non c'è alcuna utilità per questo trucco: il codice sub1 è sicuro finchè altro codice nella sua libreria non sta ridefinendo - in in qualche modo, e il compilatore può tranquillamente ottimizzare il codice basato su questo. Non c'è bisogno di trucchi intelligenti.

+0

grazie per la risposta completa! – redwoolf

2

Questa è un'ottimizzazione della velocità. L'accesso variabile locale è di solito più veloce di variabili globali.

+0

Puoi spiegarmi più dettagliatamente? Sembra che il processo di associazione con let richiederebbe tanto tempo quanto una ricerca. – redwoolf

+0

@redwoolf: la ricerca quando si esegue il binding con 'let' accade una sola volta, ma' cdr' potrebbe essere usato (e cercato) molte volte nella funzione. – Teddy

+3

Mentre questo può avere un vantaggio di velocità in alcune implementazioni, è solo un sottoprodotto della ragione più importante per farlo. Ne scriverò in una risposta separata. –

Problemi correlati