2009-03-06 12 views
17

Sto leggendo tramite SICP (Struttura e Interprete dei programmi per computer) ed ero davvero entusiasta di scoprire questa meravigliosa forma speciale: "make-environment", che dimostrano di utilizzare in combinazione con eval come un modo di scrivere codice modulare (estratto dalla sezione 4.3 "pacchetti"):Perché Scheme non supporta gli ambienti di prima classe?

(define scientific-library 
    (make-environment 
    ... 
    (define (square-root x) 
    ...))) 

hanno poi dimostrano come funziona con

((eval 'square-root scientific-library) 4) 

Nel loro esempio, hanno poi andare avanti per dimostrare esattamente l'utilizzo che avrei voglio - un modo elegante e minimalista o f facendo lo stile "OO" nello schema ... "Cons" insieme un "tipo", che è in realtà ciò che è stato restituito dal modulo speciale "make-environment" (ad es. vtable), e un ARG ("lo Stato") ...

Ero così eccitata perché questo è esattamente quello che ho cercato come un modo per fare la spedizione polimorfa "dal simbolo" nello Schema senza dover scrivere molto codice esplicito o macro.

ie Voglio creare un "oggetto" che ha, diciamo, due funzioni, che chiamo in contesti diversi ... ma non voglio farvi riferimento da "auto" e "cdr" , Voglio entrambi dichiarare e valutare con il loro nome simbolico.

In ogni caso, quando ho letto questo non vedevo l'ora di tornare a casa e provarlo.

immaginare la mia delusione quando poi ho sperimentato il seguente sia in PLT Scheme e Chez Scheme:

> (make-environment (define x 3)) 
Error: invalid context for definition (define x 3). 
> (make-environment) 
Error: variable make-environment is not bound. 

Cosa è successo a "make-ambiente", come si fa riferimento in SICP? Sembra tutto così elegante, ed esattamente quello che voglio, eppure non sembra essere supportato da nessun interprete di Scheme moderno?

Qual è la logica? È semplicemente che "make-environment" ha un nome diverso?

Maggiori informazione presente tardi

ho preso al un'occhiata alla versione on-line:

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

stavo leggendo era la prima edizione di SICP. La seconda edizione sembra aver sostituito la discussione sui pacchetti con una sezione sulla programmazione non deterministica e l'operatore "amp".

risposta

11

Dopo più scavare intorno Ho scoperto questo informative thread su Newsnet:

"Il R5RS Numeri gli specificatori di ambiente sono un compromesso tra coloro che non amano profondamente gli ambienti di prima classe e vogliono un EVAL limitato a e coloro che non possono accettare/capire EVAL senza un secondo argomento che è un ambiente. "

Inoltre, ha trovato questo "work-around":

(define-syntax make-environment 
    (syntax-rules() 
    ((_ definition ...) 
    (let ((environment (scheme-report-environment 5))) 
     (eval '(begin definition 
        ...) 
      environment) 
     environment)))) 


(define arctic 
    (make-environment 
    (define animal 'polarbaer))) 

(tratto da this)

Tuttavia, ho finito per l'adozione di un "message passing" stile un po 'come il primo ragazzo ha suggerito - ho restituire un alist di funzioni, e hanno un metodo generico "invia" per invocare una particolare funzione per nome ... cioè qualcosa di simile

(define multiply 
    (list 
    (cons 'differentiate (...)) 
    (cons 'evaluate (lambda (args) (apply * args))))) 

(define lookup 
    (lambda (name dict) 
    (cdr (assoc name dict)))) 

; Lookup the method on the object and invoke it 
(define send 
    (lambda (method arg args) 
    ((lookup method arg) args)) 

((send 'evaluate multiply) args) 

ho letto oltre e un Sono consapevole che c'è tutto CLOS se volevo davvero adottare uno stile OO completo, ma penso che anche sopra sia un po 'eccessivo.

+1

La macro make-environment è ottima, ma mi manca ancora una cosa: mi piacerebbe avere un modo per * verificare * se un simbolo è legato in un ambiente, usando solo R5RS standard, e per quanto ne so, questo non è possibile senza brutti hack come memorizzare una tabella di nomi definiti, ecc.) – Jay

+1

Hm, ho appena notato che il trucco make-environment può o non può funzionare su un'implementazione di Scheme: schema-report-environment * may * essere immutabile, e inoltre, il LET all'interno della macro potrebbe non copiare l'ambiente. Non sembra essere un modo portabile per creare un ambiente in Scheme (almeno non in R5RS). – Jay

4

Scheme non ha ambienti di prima classe a causa di motivi di prestazioni. Quando Scheme è stato creato, non era il linguaggio più veloce in circolazione a causa di elementi di qualità come le funzioni di prima classe, le continuazioni, ecc. L'aggiunta di ambienti di prima classe avrebbe paralizzato ulteriormente le prestazioni. Quindi è stato un trade-off fatto nei primi giorni dello Scheme.

+3

Avete riferimenti su questo per favore? – mnicky

1

Una normale funzione di dispatcher funzionerebbe? Penso che questo sia simile a quello che stai cercando.

(define (scientific-library f) 
    (define (scientific-square-root x) (some-scientific-square-root x)) 
    (cond ((eq? f 'square-root) scientific-square-root) 
     (else (error "no such function" f)))) 
(define (fast-library f) 
    (define (fast-square-root x) (some-fast-square-root x)) 
    (cond ((eq? f 'square-root) fast-square-root) 
     (else (error "no such function" f)))) 

((scientific-library 'square-root) 23) 
((fast-library 'square-root) 23) 

Si potrebbe anche combinare l'esempio biblioteche scientifiche e veloci in un grande metodo di spedizione:

(define (library l f) 
    (define (scientific-library f) 
    ...) 
    (define (fast-library f) 
    ...) 
    (cond ((eq? l 'scientific) (scientific-library f)) 
     ((eq? l 'fast) (fast-library f)) 
     (else (error "no such library" l)))) 
(library 'fast 'square-root) 
+0

Sì, ma scrivere quanto sopra è così noioso e prolisso! –

4

Lo hanno scritto così perché il MIT Scheme ha, in effetti, ambienti di prima classe, e presumibilmente è quello che gli scrittori stavano progettando di insegnare alla loro classe (dal momento che il libro è stato scritto al MIT).

Partenza http://groups.csail.mit.edu/mac/projects/scheme/

Tuttavia, ho notato che il MIT Scheme, mentre ancora sviluppato un po 'attivamente, manca di molte delle caratteristiche che un sistema davvero moderno avrebbe, come una funzione di interfaccia straniera o di supporto GUI. Probabilmente non vorresti usarlo per un serio progetto di sviluppo software, almeno non da solo.

Problemi correlati