为什么 Scheme 不支持一流的环境? [英] Why doesn't Scheme support first class environments?
问题描述
我一直在通读 SICP(计算机程序的结构和解释)并且非常兴奋地发现了这种奇妙的特殊形式:make-environment",他们证明将其与 eval 结合使用作为编写模块化的一种方式代码(摘自第 4.3 节包"):
I've been reading through SICP (Structure and Interpration of Computer Programs) and was really excited to discover this wonderful special form: "make-environment", which they demonstrate to use in combination with eval as a way of writing modular code (excerpt from section 4.3 on "packages"):
(define scientific-library
(make-environment
...
(define (square-root x)
...)))
然后他们演示它是如何工作的
They then demonstrate how it works with
((eval 'square-root scientific-library) 4)
在他们的例子中,他们接着完全演示了我想要的用法——一种优雅的、极简主义的在方案中实现OO"风格的方式......他们一起cons"一个类型",实际上是由make-environment"特殊形式(即 vtable)和一个 arg(状态")返回的......
In their example, they then go on to demonstrate exactly the usage that I would want - an elegant, minimalist way of doing the "OO" style in scheme... They "cons" together a "type", which is actually what was returned by the "make-environment" special form (i.e. the vtable), and an arg ("the state")...
我非常兴奋,因为这正是我一直在寻找一种在 Scheme 中按符号"进行多态分派的方法,而无需编写大量显式代码或宏.
I was so excited because this is exactly what I've been looking for as a way to do polymorphic dispatch "by symbol" in Scheme without having to write lots of explicit code or macros.
即我想创建一个具有两个函数的对象",我在不同的上下文中调用它们......但我不想用car"和cdr"来引用它们,我想通过它们的符号名称声明和评估它们.
i.e. I want to create an "object" that has, say, two functions, that I call in different contexts... but I don't want to refer to them by "car" and "cdr", I want to both declare and evaluate them by their symbolic names.
无论如何,当我读到这篇文章时,我迫不及待地想回家试试.
Anyway, when I read this I couldn't wait to get home and try it.
想象一下,当我在 PLT Scheme 和 Chez Scheme 中遇到以下情况时我的失望:
Imagine my disappointment then when I experienced the following in both PLT Scheme and Chez Scheme:
> (make-environment (define x 3))
Error: invalid context for definition (define x 3).
> (make-environment)
Error: variable make-environment is not bound.
SICP 中提到的make-environment"发生了什么变化?这一切看起来都很优雅,正是我想要的,但似乎没有任何现代 Scheme 解释器支持它?
What happened to "make-environment" as referenced in SICP? It all seemed so elegant, and exactly what I want, yet it doesn't seem to be supported in any modern Scheme interpreters?
这是什么原理?仅仅是make-environment"有不同的名称吗?
What's the rationale? Is it simply that "make-environment" has a different name?
稍后找到更多信息
我看了一下网络版:
http://mitpress.mit.edu/sicp/full-text/book/book-ZH-28.html#%_sec_4.3
我读的是SICP的第一版.第二版似乎用非确定性编程和amp"运算符的部分取代了对包的讨论.
I was reading was the first edition of SICP. The second edition appears to have replaced the discussion on packages with a section on non-deterministic programming and the "amp" operator.
推荐答案
经过更多的挖掘,我发现了这个 信息线程:
After more digging around I discovered this informative thread on newsnet:
R5RS EVAL 和环境说明符是两者之间的折衷那些非常不喜欢一流环境并想要一个受限制的EVAL,以及无法接受/理解EVAL的人第二个参数是环境."
"The R5RS EVAL and environment specifiers are a compromise between those who profoundly dislike first-class environments and want a restricted EVAL, and those who can not accept/understand EVAL without a second argument that is an environment."
另外,找到了这个解决方法":
Also, found this "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)))
(取自 这个)
然而,我最终采用了一种类似于第一个人建议的消息传递"风格——我返回一个函数列表,并有一个通用的发送"方法来按名称调用特定函数......即某些东西像这样
However, I ended up adopting a "message passing" style kinda of like the first guy suggested - I return an alist of functions, and have a generic "send" method for invoking a particular function by name... i.e something like this
(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)
我一直在进一步阅读,并且我知道如果我真的想采用完全面向对象的风格,那么 CLOS 就有了 - 但我认为即使在上面也有点矫枉过正.
I've been reading further and am aware that there's all of CLOS if I really wanted to adopt a fully OO style - but I think even above is somewhat overkill.
这篇关于为什么 Scheme 不支持一流的环境?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!