【问题标题】:Scheme and Shallow Binding方案和浅绑定
【发布时间】:2013-02-21 22:14:17
【问题描述】:
 (define make (lambda (x) (lambda (y) (cons x (list y)))))

 (let ((x 7)
       (p (make 4)))
   (cons x (p 0)))

我是 Scheme 和函数式程序的新手,所以我在浏览程序时有点笨拙,但我知道如果我使用深度绑定,这个程序将返回 (7 4 0)。说得通。这个程序使用浅绑定会做什么?我知道这听起来可能很愚蠢,但是与 cons 一致的 p 是重新定义吗?所以在那种情况下,我们会返回 (7 0)?

基本上,我理解 deep v. shallow binding 的概念,但我觉得在看 Scheme 时我把它搞混了,因为我对它并不熟悉。

【问题讨论】:

    标签: binding scheme


    【解决方案1】:

    深层或浅层绑定是一种实现技术,无法从程序内部观察到。程序员的区别在于词法和动态范围规则之间,但两者都可以使用两种技术中的任何一种来实现(即一个概念与另一个无关)。

    深或浅是指选择堆栈帧来保存给定外部范围变量的绑定。在深度绑定中,需要访问一系列帧,直到输入正确的帧来保存变量的记录;在浅层绑定中,所有绑定都存在于一个浅层环境中。另请参阅“rerooting”(仅在词法范围的浅绑定实现的上下文中才有意义)。

    对于您的具体问题,在 lexical 范围规则下,您的代码将返回 (7 4 0) 并在 dynamic - (7 7 0) 下,因为调用 ((lambda(y) (list x y)) 0) 在内部完成x=7 绑定的动态范围(作为旁注,(cons x (list y))(list x y) 相同):

    x = 7
    p = (lambda (y) (list x y))      ; x=4 is unused, in p=(make 4)
    (cons 7 (p 0)) == (list 7 7 0)   ; 'x' in this line and in lambda body for p
                                     ;   both refer to same binding that is
                                     ;   in effect, i.e. x=7
    

    NB 相同的术语(深/浅绑定)现在在其他语言中使用完全不同的含义(它们确实与那里的范围规则有关),我不想完全理解。这个答案是在 Scheme 的上下文中给出的。

    参考:Shallow Binding in LISP 1.5 Baker,Henry G. Jr.,1977 年。

    【讨论】:

    • 一些教师和教科书作者认为可以观察到深绑定或浅绑定之间的差异,并给学生分配作业来编写一个程序,该程序会根据在 PL 实现中实现的绑定类型给出不同的结果。那而不是教一些有用的东西。词汇和动态作用域之间的区别是一种经院哲学,因为没有人使用动态作用域。深装或浅装之间的区别更大的是经院哲学。 :-(
    • @beroal 我的回答是关于 Lisp 世界的原始概念。一些pythonistas(或其他东西)非常困惑(并且令人困惑)使用这个术语来表示完全不同的东西。您的评论可能指的是后者,我的回答涉及前者。此外,很多人在很多情况下都使用动态绑定。认为 EMACS Lisp 是一方面。 (顺便说一句,没有动态范围,“范围”意味着“词法”)。深/浅绑定(原始概念)仅适用于语言实现者,而不适用于用户。这是一种有效的技术,可以适合例如在 Lisp->C 翻译器中。
    【解决方案2】:

    请参阅此 wikipedia article 了解有关范围的讨论(它提到了词法/动态范围和深/浅绑定),记住 Scheme 是词法范围的。 Will Ness 的回答提供了更多信息。 现在,让我们一步一步地看看这段代码的 sn-p 中发生了什么:

    ; a variable called x is defined and assigned the value 7
    (let ((x 7)
    ; make is called and returns a procedure p, inside its x variable has value 4
          (p (make 4)))
    ; 7 is appended at the head of the result of calling p with y = 0
      (cons x (p 0)))
    
    => '(7 4 0)
    

    请注意,在第二行中,在 make 返回的 lambda 中创建了一个 闭包,其中的变量 x 将被赋值为 4。这个x 与外部x 无关,因为Scheme 是词法范围的。

    最后一行不是重新定义,如上一段所述,make 中的xlet 表达式中定义的x 不同。

    【讨论】:

    • AFAIK 这是错误的。浅/深绑定与静态/动态范围完全正交。两者都可以用来实现两者。查找“rerooting”,它只在静态作用域的浅绑定 impl'n 中有意义。
    • @WillNess 也许你可以建议一种方法来改写第一句话?其余的答案都是正确的,无需投反对票。最好提供建设性的反馈。
    • 我不认为我在这里没有建设性。第一段总体上(曾经)明显是错误的,我别无选择,只能投反对票,抱歉。 :) 它只能被删除,或者完全重写。 (最小的编辑....完成。:))
    • @WillNess 好的,同意。我对其进行了编辑,并提及了您的回答;)
    猜你喜欢
    • 2017-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多