浅及深绑定 [英] Shallow and Deep Binding

查看:810
本文介绍了浅及深绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是想了解有深深浅浅的结合动态/静态范围的概念。下面是code -

 (定义X 0)
(定义ÿ0)
(定义(F Z)(显示(+ Z Y))
(定义(G + F)(让((Y 10))(F X)))
(定义(H)(让((×100))(G + F)))
(H)

我在调用函数的动态作用域值理解用于被调用的函数。因此,使用动态绑定我应该得到的答案 - 110 。使用静态作用域我会得到答案 0 。但我得到这些结果没有考虑浅或深的结合。什么是浅及深的绑定和它将如何改变结果?


解决方案

有在这些讲义一个例子的 6。名称,范围和绑定:解释的概念,虽然我不喜欢他们的伪code:


  THRES:整数
旧的功能(P:人):布尔
  返回p.age> THRES
程序显示(号码:人,C:功能)
  THRES:整数
  THRES:= 20
  如果C(P)
    写(p)的
过程主要(p)的
  THRES:= 35
  秀(P,老年)


尽我所知,这将是计划如下(有一些,我希望更多的描述性名称:

(定义截止0);一个 (定义(上面截止?人)
     (大于(年龄人)截止)) (定义(显示,如果人predicate)
     (让((截止20)); B
       (如果(predicate人)
           (显示人)))) (定义(主要负责人)
     (让((截止35)),C
       (显示,如果人以上截止?)))


  • 随着词法范围在截止上面截止?通常是指结合

  • 使用,因为它Common Lisp中的实现动态作用域(与动态作用域最实际的语言,我认为),截止上述截止价值?,当作为在predicate的显示,如果后,将把绑定的,因为这是最近一次在这种情况下,堆栈上。这是的浅连结

  • 那么剩下的选项的深连结的,它有内有截止的价值影响的上面截止?指结合 C

现在,让我们来看看你的例子:


  

(定义X 0)
(定义ÿ0)
(定义(F Z)(显示(+ Z Y))
(定义(G + F)(让((Y 10))(F X)))
(定义(H)(让((×100))(G + F)))
(H)


我要添加一些新行,使注释更容易,并使用注释来标记每一个被束缚一次以上的变量的每个绑定。

(定义X 0); X0
 (定义ÿ0); Y0
 (定义(F Z); F0
     (显示(+ Z Y)))
 (定义(G + F); F1
     (让((Y 10)); Y1
       (F X)))
 (定义(H)
     (让((×100)); X1
       (G + F)))

请注意在F0和F1在那里。这些都是重要的,因为在深绑定,作为参数传递函数的当前环境绑定到该环境。这一点很重要,因为˚F作为参数传递给˚F。所以,让我们涵盖所有情况:


  • 在词汇范围,结果为0。我认为这是最简单的情况。

  • 使用动态范围和浅约束力的答案是110(Z值是100,和y的值是10),那是你已经知道如何得到答案。

  • 最后,动态范围和深连结,你会得到100内的 ^ h ,你通过的˚F作为参数,而目前的范围捕获给我们一个函数(拉姆达(Z)(显示(+ Z 0))),我们称之为 FF 为了方便。有一次,你在,调用局部变量的˚F实际上是一个通话的 FF ,这就是所谓的当前值中的 X (从 X1 的,100),所以你要打印的(100 + 0),这是100。

注释

正如我所说的,我觉得深的结合是有点不寻常,我不知道有多少语言是否真正实施。你可以把它看成服用功能,检查是否有任何自由变量,然后在值从目前的动态环境填充它们。我不认为这实际上被使用在实践中多,这可能是为什么你收到<一个href=\"http://stackoverflow.com/questions/34051146/shallow-and-deep-binding#comment55865995_34051146\">some评论询问这些条款。我也看到,它可能是在某些情况下是有用的,但。例如,在常见Lisp,其具有既词法和动态(称为特殊)变量,许多系统配置​​参数是动态的。这意味着你可以做这样的事情在基地16打印(因为 *打印基数* 是一个动态的变量):

 (让((*打印基数* 16))
  (打印值))

但是,如果你想返回,将打印底座16的东西的功能,你可以这样做:

 (让((*打印基数* 16))
  (拉姆达(值)
    (打印值)))

因为有人可能会采取功能,我们称之为 print16 ,然后做的:

 (让((*打印基数* 10))
  (print16值))

和值将以10为基数深印结合将避免这个问题。这就是说,你还可以结合浅避免它;你可以返回

 (拉姆达(值)
  (让((*打印基数* 16))
    (打印值)))

代替。

所有这一切说,我认为这种讨论时,在谈论传递函数作为参数得到那样的陌生。这很奇怪,因为在大多数语言中,一个前pression 的评估产生的的。 A 变量的是一种类型的前pression,而的评估变量的结果的的前$ P $变量的pssion 。我强调的那里,因为这是它是:一个变量在任何给定时间的单个值。深深浅浅的绑定此presentation使得它给一个变量不同的值取决于它被评估。这似乎是pretty奇怪。我认为将使更多的意义是,如果讨论是什么,你回来当你评估的拉姆达前pression 的。然后,你可以问将在拉姆达前pression自由变量的值是?答案,在浅水结合,将是无论这些变量的动态值是在函数被后来被称为,答案,深约束力,是无论这些变量的动态值是当拉姆达前pression被评为

那么我们就不必考虑功能被作为参数传递。 作为参数传递功能的全是离奇的,因为当你传递一个函数作为参数(其捕捉动态环境下),会发生什么,无论您正在传递它然后传递到其他地方?是动态的环境应该得到重新绑定?

相关问题与解答

I was trying to understand the concept of dynamic/static scope with deep and shallow binding. Below is the code-

(define x 0)
(define y 0)
(define (f z) (display ( + z y))
(define (g f) (let ((y 10)) (f x)))
(define (h) (let ((x 100)) (g f)))
(h)

I understand at dynamic scoping value of the caller function is used by the called function. So using dynamic binding I should get the answer- 110. Using static scoping I would get the answer 0. But I got these results without considering shallow or deep binding. What is shallow and deep binding and how will it change the result?

解决方案

There's an example in these lecture notes 6. Names, Scopes, and Bindings: that explains the concepts, though I don't like their pseudo-code:

thres:integer
function older(p:person):boolean
  return p.age>thres
procedure show(p:person, c:function)
  thres:integer
  thres:=20
  if c(p)
    write(p)
procedure main(p)
  thres:=35
  show(p, older)

As best I can tell, this would be the following in Scheme (with some, I hope, more descriptive names:

 (define cutoff 0)                      ; a 

 (define (above-cutoff? person)
     (> (age person) cutoff))

 (define (display-if person predicate)
     (let ((cutoff 20))                 ; b
       (if (predicate person)
           (display person))))

 (define (main person)
     (let ((cutoff 35))                 ; c
       (display-if person above-cutoff?)))

  • With lexical scoping the cutoff in above-cutoff? always refers to binding a.
  • With dynamic scoping as it's implemented in Common Lisp (and most actual languages with dynamic scoping, I think), the value of cutoff in above-cutoff?, when used as the predicate in display-if, will refer to binding b, since that's the most recent on on the stack in that case. This is shallow binding.
  • So the remaining option is deep binding, and it has the effect of having the value of cutoff within above-cutoff? refer to binding c.

Now let's take a look at your example:

(define x 0)
(define y 0)
(define (f z) (display (+ z y))
(define (g f) (let ((y 10)) (f x)))
(define (h) (let ((x 100)) (g f)))
(h)

I'm going to add some newlines so that commenting is easier, and use a comment to mark each binding of each of the variables that gets bound more than once.

 (define x 0)                           ; x0
 (define y 0)                           ; y0 
 (define (f z)                          ; f0 
     (display (+ z y)))
 (define (g f)                          ; f1
     (let ((y 10))                      ; y1
       (f x)))
 (define (h)
     (let ((x 100))                     ; x1
       (g f)))

Note the f0 and f1 there. These are important, because in the deep binding, the current environment of a function passed as an argument is bound to that environment. That's important, because f is passed as a parameter to g within f. So, let's cover all the cases:

  • With lexical scoping, the result is 0. I think this is the simplest case.
  • With dynamic scoping and shallow binding the answer is 110. (The value of z is 100, and the value of y is 10.) That's the answer that you already know how to get.
  • Finally, dynamic scoping and deep binding, you get 100. Within h, you pass f as a parameter, and the current scope is captured to give us a function (lambda (z) (display (+ z 0))), which we'll call ff for sake of convenience. Once, you're in g, the call to the local variable f is actually a call to ff, which is called with the current value of x (from x1, 100), so you're printing (+ 100 0), which is 100.

Comments

As I said, I think the deep binding is sort of unusual, and I don't know whether many languages actually implement that. You could think of it as taking the function, checking whether it has any free variables, and then filling them in with values from the current dynamic environment. I don't think this actually gets used much in practice, and that's probably why you've received some comments asking about these terms. I do see that it could be useful in some circumstances, though. For instance, in Common Lisp, which has both lexical and dynamic (called 'special') variables, many of the system configuration parameters are dynamic. This means that you can do things like this to print in base 16 (since *print-radix* is a dynamic variable):

(let ((*print-radix* 16))
  (print value))

But if you wanted to return a function that would print things in base 16, you can't do:

(let ((*print-radix* 16))
  (lambda (value)
    (print value)))

because someone could take that function, let's call it print16, and do:

(let ((*print-radix* 10))
  (print16 value))

and the value would be printed in base 10. Deep binding would avoid that issue. That said, you can also avoid it with shallow binding; you just return

(lambda (value)
  (let ((*print-radix* 16))
    (print value)))

instead.

All that said, I think that this discussion gets kind of strange when it's talking about "passing functions as arguments". It's strange because in most languages, an expression is evaluated to produce a value. A variable is one type of expression, and the result of evaluating a variable is the expression of that variable. I emphasize "the" there, because that's how it is: a variable has a single value at any given time. This presentation of deep and shallow binding makes it gives a variable a different value depending on where it is evaluated. That seems pretty strange. What I think would make much more sense is if the discussions were about what you get back when you evaluate a lambda expression. Then you could ask "what will the values of the free variables in the lambda expression be"? The answer, in shallow binding, will be "whatever the dynamic values of those variables are when the function is called later. The answer, in deep binding, is "whatever the dynamic values of those variables are when the lambda expression is evaluated."

Then we wouldn't have to consider "functions being passed as arguments." The whole "functions being passed as arguments" is bizarre, because what happens when you pass a function as a parameter (capturing its dynamic environment) and whatever you're passing it to then passes it somewhere else? Is the dynamic environment supposed to get re-bound?

Related Questions and Answers

这篇关于浅及深绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆