Domanda

Ho letto tramite SICP (Struttura e interpretazione dei programmi per computer) ed ero davvero entusiasta di scoprire questa meravigliosa forma speciale: "make-environment", che dimostrano di usare in combinazione con eval come modo di scrivere codice modulare (estratto dalla sezione 4.3 su "pacchetti"):

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

Dimostrano quindi come funziona

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

Nel loro esempio, continuano poi a dimostrare esattamente l'uso che vorrei - un modo elegante e minimalista di fare il "OO" stile nello schema ... Essi "contro". insieme un "tipo", che in realtà è ciò che è stato restituito dal "make-environment" forma speciale (cioè la vtable) e un arg ("lo stato") ...

Ero così eccitato perché questo è esattamente quello che stavo cercando come un modo per fare un invio polimorfico "per simbolo". nello schema senza dover scrivere un sacco di codice esplicito o macro.

vale a dire. Voglio creare un " oggetto " che ha, diciamo, due funzioni che io chiamo in contesti diversi ... ma non voglio fare riferimento a loro con "auto" e " cdr " ;, voglio sia dichiarare sia valutarli con i loro nomi simbolici.

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

Immagina la mia delusione quando ho provato quanto segue sia nello schema PLT che nello schema Chez:

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

Che cosa è successo a " make-environment " come indicato in SICP? Sembrava tutto così elegante, ed esattamente quello che voglio, eppure non sembra essere supportato in nessun moderno interprete di Scheme?

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

Ulteriori informazioni trovate in seguito

Ho dato un'occhiata alla versione online:

http: // mitpress .mit.edu / SICP / full-text / libro / book-ZH-28.html #% _ sec_4.3

Stavo leggendo la prima edizione di SICP. La seconda edizione sembra aver sostituito la discussione sui pacchetti con una sezione sulla programmazione non deterministica e l'amplificazione & amp; operatore.

È stato utile?

Soluzione

Dopo ulteriori ricerche ho scoperto questo thread informativo su newsnet:

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

Inoltre, ho 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 questo )

Tuttavia, ho finito per adottare un messaggio che passa " stile un po 'come il primo ragazzo ha suggerito: restituisco una lista di funzioni e ho un generico "invia" metodo 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 di più e sono consapevole che c'è tutto CLOS se volessi davvero adottare uno stile completamente OO - ma penso che anche sopra sia un po 'eccessivo.

Altri suggerimenti

Lo schema non ha ambienti di prima classe per motivi di prestazioni. Quando è stato creato Scheme, non era il linguaggio più veloce in circolazione a causa di cose ingegnose come funzioni di prima classe, continuazioni, ecc. L'aggiunta di ambienti di prima classe avrebbe compromesso ulteriormente le prestazioni. Quindi è stato un compromesso fatto nei primi giorni dello Schema.

L'hanno scritto in questo modo perché il MIT Scheme ha, di fatto, ambienti di prima classe, e presumibilmente è quello con cui gli scrittori stavano progettando di insegnare alla loro classe (da quando il libro è stato scritto al MIT).

Scopri http://groups.csail.mit.edu/mac/ progetti / programma /

Tuttavia, ho notato che il MIT Scheme, sebbene ancora in qualche modo sviluppato attivamente, manca di molte delle caratteristiche che avrebbe uno Schema davvero moderno, come un'interfaccia di funzione esterna o il supporto della GUI. Probabilmente non vorrai usarlo per un serio progetto di sviluppo software, almeno non da solo.

Una funzione di dispatcher classico 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)

Potresti anche combinare le biblioteche scientifiche e veloci di esempio in un unico 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)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top