ropa - ¿Por qué Scheme no admite entornos de primera clase?
racket ropa (4)
¿Funcionaría un despachador clásico? 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 podría combinar el ejemplo de bibliotecas científicas y rápidas en un método de envío 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)
He estado leyendo a través de SICP (Estructura e interpretación de programas de computadora) y me entusiasmó mucho 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 sobre "paquetes"):
(define scientific-library
(make-environment
...
(define (square-root x)
...)))
Luego demuestran cómo funciona
((eval ''square-root scientific-library) 4)
En su ejemplo, luego continúan demostrando exactamente el uso que yo quisiera: una forma elegante y minimalista de hacer el estilo "OO" en el esquema ... Ellos "en contra" forman un "tipo", que en realidad es lo que era devuelto por el formulario especial "make-environment" (es decir, el vtable), y un argumento ("el estado") ...
Estaba tan emocionado porque esto es exactamente lo que he estado buscando como una manera de hacer un envío polimórfico "por símbolo" en Esquema sin tener que escribir muchos códigos explícitos o macros.
es decir, quiero crear un "objeto" que tenga, digamos, dos funciones, a las que llamo en diferentes contextos ... pero no quiero referirme a ellas con "coche" y "cdr", quiero declarar ambas Y evaluarlos por sus nombres simbólicos.
De todos modos, cuando leí esto no podía esperar a llegar a casa e intentarlo.
Imagina mi decepción cuando experimenté lo siguiente tanto en PLT Scheme como en Chez Scheme:
> (make-environment (define x 3))
Error: invalid context for definition (define x 3).
> (make-environment)
Error: variable make-environment is not bound.
¿Qué pasó con "make-environment" como se menciona en SICP? ¿Todo parecía tan elegante y exactamente lo que quiero, pero parece que no hay soporte para ningún intérprete de Scheme moderno?
¿Cuál es la razón? ¿Es simplemente que "make-environment" tiene un nombre diferente?
Más información encontrada más adelante.
Eché un vistazo a la versión en línea:
http://mitpress.mit.edu/sicp/full-text/book/book-Z-H-28.html#%_sec_4.3
Yo estaba leyendo fue 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 "amplificador".
Después de investigar más, descubrí este hilo informativo en newsnet:
"El R5RS EVAL y los especificadores de entorno son un compromiso entre los que no les gustan profundamente los entornos de primera clase y desean un EVAL restringido, y los que no pueden aceptar / entender EVAL sin un segundo argumento que es un entorno".
También, encontré este "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)))
(tomado de this )
Sin embargo, terminé adoptando un estilo de "paso de mensajes" como el que sugirió el primer tipo: devuelvo una lista de funciones y tengo un método genérico de "envío" para invocar una función particular por 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 estoy consciente de que hay CLOS si realmente quería adoptar un estilo totalmente OO, pero creo que incluso más arriba es un poco excesivo.
Lo escribieron así porque, de hecho, el Esquema MIT tiene ambientes de primera clase, y presumiblemente eso es lo que los escritores planeaban enseñar a su clase (desde que el libro fue escrito en el MIT).
Echa un vistazo a http://groups.csail.mit.edu/mac/projects/scheme/
Sin embargo, me he dado cuenta de que el Esquema MIT, aunque todavía está desarrollado de forma activa, carece de muchas de las características que tendría un Esquema realmente moderno, como una interfaz de función externa o soporte GUI. Probablemente no querrá usarlo para un proyecto serio de desarrollo de software, al menos no solo.
Scheme no tiene entornos de primera clase debido a razones de rendimiento. Cuando se creó Scheme, no era el lenguaje más rápido debido a cosas ingeniosas como funciones de primera clase, continuaciones, etc. Agregar entornos de primera clase habría paralizado aún más el rendimiento. Así que fue una compensación hecha en los primeros días del Esquema.