【问题标题】:Why doesn't Scheme support first class environments?为什么 Scheme 不支持一流的环境?
【发布时间】:2010-10-11 15:59:25
【问题描述】:

我一直在阅读 SICP(计算机程序的结构和解释),并且非常兴奋地发现了这种奇妙的特殊形式:“make-environment”,他们演示了将其与 eval 结合使用作为编写模块化的一种方式代码(摘自第 4.3 节“包”):

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

然后他们演示它是如何工作的

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

在他们的示例中,然后他们继续演示完全我想要的用法 - 一种优雅、简约的方式在方案中执行“OO”样式...他们“cons”在一起一个“类型”,实际上是“make-environment”特殊形式(即vtable)返回的内容,以及一个arg(“状态”)......

我非常兴奋,因为这正是我一直在寻找的一种方法,可以在 Scheme 中“按符号”进行多态调度,而无需编写大量显式代码或宏。

即我想创建一个“对象”,它有,比如说,两个函数,我在不同的上下文中调用......但我不想用“car”和“cdr”来引用它们,我想通过它们的符号名称来声明评估它们。

无论如何,当我读到这篇文章时,我迫不及待地想回家尝试一下。

想象一下,当我在 PLT 计划和 Chez 计划中遇到以下情况时,我会感到失望:

> (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 解释器都不支持它?

理由是什么?仅仅是“make-environment”的名称不同吗?

更多信息稍后发现

我看了看在线版本:

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

我读的是SICP的第一版。第二版似乎用关于非确定性编程和“amp”运算符的部分取代了对包的讨论。

【问题讨论】:

    标签: scheme racket


    【解决方案1】:

    经过更多的挖掘,我在新闻网上发现了这个informative thread

    “R5RS EVAL 和环境说明符是 那些极度不喜欢一流环境并想要一个 受限制的 EVAL,以及那些无法接受/理解 EVAL 的人 第二个参数是环境。”

    另外,找到了这个“解决方法”:

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

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

    我一直在进一步阅读,并且知道如果我真的想采用完全 OO 样式,那么所有的 CLOS 都可以 - 但我认为即使是上面的内容也有些过头了。

    【讨论】:

    • make-environment 宏很棒,但我仍然想念一件事:我想有一种方法来验证符号是否绑定在环境中,使用只有标准的 R5RS,据我所知,如果没有丑陋的 hack,比如存储定义名称的表等,这是不可能的)
    • 嗯,我刚刚注意到 make-environment 技巧可能会或可能不会在 Scheme 实现上起作用:scheme-report-environment 可能是不可变的,而且 LET宏里面可能不会复制环境。在 Scheme 中似乎没有一种可移植的方式来创建环境(至少在 R5RS 中没有)。
    【解决方案2】:

    他们之所以这样写,是因为 MIT Scheme 实际上确实拥有一流的环境,并且大概这就是作者计划用它来教授他们的班级的(因为这本书是在 MIT 写的)。

    查看http://groups.csail.mit.edu/mac/projects/scheme/

    但是,我注意到 MIT 方案虽然仍在积极开发中,但缺乏真正现代方案应具备的许多功能,例如外来函数接口或 GUI 支持。您可能不想将它用于严肃的软件开发项目,至少不会单独使用它。

    【讨论】:

      【解决方案3】:

      由于性能原因,Scheme 没有一流的环境。在创建 Scheme 时,由于一流的函数、延续等漂亮的东西,它并不是最快的语言。添加一流的环境会进一步削弱性能。所以这是在早期 Scheme 时代做出的权衡。

      【讨论】:

      • 请问您有这方面的参考资料吗?
      【解决方案4】:

      经典的调度程序功能会起作用吗?我认为这与您正在寻找的相似。

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

      您甚至可以将示例科学和快速库组合成一个大型调度方法:

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

      【讨论】:

      • 是的,但是上面写的太乏味和冗长了!
      猜你喜欢
      • 2022-01-27
      • 1970-01-01
      • 1970-01-01
      • 2017-08-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-12
      • 1970-01-01
      相关资源
      最近更新 更多