2009-03-06 15 views
17

He estado leyendo a través de SICP (Estructura e Interpración de Programas de Computadora) y estaba realmente emocionado de descubrir esta maravillosa forma especial: "make-environment", que demuestran usar en combinación con eval como una forma de escribir código modular (extracto de la sección 4.3 en "paquetes"):¿Por qué Scheme no admite entornos de primera clase?

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

a continuación demuestran cómo funciona con

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

en su ejemplo, y luego ir a demostrar exactamente el uso que lo haría querer - una manera elegante, minimalista o f haciendo el estilo "OO" en el esquema ... Ellos "contras" juntos un "tipo", que en realidad es lo que fue devuelto por la forma especial "hacer entorno" (es decir, la viable), y un arg ("Estado") ...

Estaba tan emocionado porque esto es exactamente lo que he estado buscando como una manera de hacer el envío polimórfica "por el símbolo" en el Esquema sin tener que escribir muchos códigos explícitos o macros.

Es decir, quiero crear un "objeto" que tenga, digamos, dos funciones, que llamo en diferentes contextos ... pero no quiero referirme a ellas por "coche" y "cdr" , Quiero tanto declarar y evaluar por sus nombres simbólicos.

De todos modos, cuando leí esto, no podía esperar para llegar a casa y probarlo.

imaginar mi decepción entonces cuando experimenté lo siguiente en tanto PLT Scheme y Chez Esquema:

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

¿Qué le pasó a "hacer-medio ambiente" como se indica en SICP? Todo parecía tan elegante, y exactamente lo que quiero, sin embargo, no parece ser compatible con ningún intérprete moderno de Scheme.

¿Cuál es el motivo? ¿Es simplemente que "make-environment" tiene un nombre diferente?

Más información encontrado más tarde

que tomé en vistazo a la versión en línea:

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

que estaba leyendo era la primera edición de SICP. La segunda edición parece haber reemplazado la discusión sobre paquetes con una sección sobre programación no determinista y el operador "amp".

Respuesta

11

Después de más escarbar descubrí este informative thread en la red de noticias:

"El R5RS EVAL y los especificadores de entorno son un compromiso entre los que no les gustan los entornos de primera clase y quieren un EVAL restringido , y aquellos que no pueden aceptar/comprender EVAL sin un segundo argumento que es un entorno ".

Además, encontraron esta "solución temporal":

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

(tomado de this)

Sin embargo, terminé la adopción de un "paso de mensajes" estilo un poco de como el primer chico sugirió - Puedo devolver una alista de funciones, y tener un método genérico de "enviar" para invocar una función particular por su nombre ... es decir algo como esto

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

he estado leyendo más y una Estoy consciente de que hay todos los CLOS si realmente quisiera adoptar un estilo completamente OO, pero creo que incluso arriba es algo exagerado.

+1

El macro make-environment es genial, pero todavía echo de menos una cosa: me gustaría tener una forma de * verificar * si un símbolo está enlazado en un entorno, usando solo R5RS estándar, y hasta donde yo sé, esto no es posible sin feos hacks como almacenar una tabla de nombres definidos, etc.) – Jay

+1

Hm, acabo de notar que el truco de make-environment puede o no funcionar en una implementación de Scheme: scheme-report-environment * may * puede ser inmutable, y también, el LET dentro de la macro puede no copiar el entorno. No parece haber una forma portátil de crear un entorno en Scheme (al menos no en R5RS). – Jay

4

Scheme no tiene entornos de primera clase por motivos de rendimiento. Cuando se creó Scheme, no era el lenguaje más rápido que existía debido a cosas ingeniosas como funciones de primera clase, continuaciones, etc. La adición de entornos de primera clase habría paralizado aún más el rendimiento. Entonces fue una transacción hecha en los primeros días del Scheme.

+3

¿Tiene alguna referencia sobre esto por favor? – mnicky

1

¿Funcionaría una función despachadora clásica? Creo que esto es similar a lo que estás buscando.

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

Incluso se puede combinar el ejemplo bibliotecas científicas y rápidas en un método de despacho grande:

(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í, pero escribir lo anterior es muy tedioso y prolijo. –

4

Lo escribieron así porque MIT Scheme, de hecho, tiene entornos de primera clase, y presumiblemente eso es lo que los escritores planean enseñar a su clase (ya que el libro fue escrito en MIT).

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

Sin embargo, me he dado cuenta de que el MIT Esquema, mientras que todavía se desarrolló un poco activa, carece de muchas de las características que un esquema muy moderno tendría, como una función de interfaz externa o soporte GUI. Probablemente no desee usarlo para un proyecto serio de desarrollo de software, al menos no solo.

Cuestiones relacionadas