【问题标题】:Why this expression does not unbound the variable?为什么这个表达式没有解绑变量?
【发布时间】:2015-12-24 12:03:36
【问题描述】:

最近我开始学习 Erlang,来自命令式背景的东西有些不同......

我做得很好(学习 Erlang),直到我在 Eshell 工作时遇到了一些我不理解的东西,有人可以解释一下发生了什么吗?

17> One.
1
18> One = 1.
1
19> true andalso f(One).
ok
20> One.
1

为什么One 仍然绑定到一个值?由于确实评估了表达式的右侧。现在,如果我单独使用f(),一切都会按预期进行

21> f(One).
ok
22> One.
* 1: variable 'One' is unbound

为什么?

【问题讨论】:

标签: erlang


【解决方案1】:

假设当前没有变量绑定,命令

1> One = 1.

通过调用erl_eval:add_binding('One',1,[]) 添加One 的绑定,其中最后一个参数是当前绑定的列表。然后绑定是[{'One',1}]

接下来,我们运行andalso 表达式:

2> true andalso f(One).
ok
3> b().
One = 1
ok

此命令发生的情况是,当true 被评估时,绑定为[{One,1}]。由于true 使andalso 的左侧成功,然后评估右侧,也使用[{One,1}] 的绑定,并且f(One) 命令导致对erl_eval:del_binding('One',[{'One',1}]) 的调用,将右侧的绑定更改为空列表[]。由于andalso 的工作方式,这部分表达式的结果ok 成为整体结果。一旦该结果可用,右侧的绑定将被删除,因为所需要的只是结果。由于左侧,原始绑定仍然存在,并且这些绑定保持有效。因此,用于显示绑定的后续b() 命令仍然显示One = 1

如果你运行这个,会发生非常相似的效果:

4> true andalso (Two = 2).
2
5> b().
One = 1
ok

andalso 的第二部分 (Two = 2) 仅将 Two 的绑定添加到评估的该部分的绑定中。结果 2 被保留,但该部分的绑定被删除,只有左半部分的绑定保持有效。当我们再次运行b() 来查看所有绑定时,我们仍然只能看到One = 1

【讨论】:

  • 好的,我明白了,非常感谢。但是,发生了什么事?我的意思是,你说The original bindings are still around because of the left-hand side 是什么意思?你的意思是,Erlang 为布尔表达式创建了另一个作用域?另外,这个逻辑是否适用于 shell 之外?
  • 首先,这仅发生在 shell 中,因为 f 是一个特定于 shell 的函数,如果您尝试编译我的第二个示例(包含 Two=2),编译器将失败并显示错误 @ 987654350@,表示不是所有的表达式分支都设置Two。 Erlang 不会为布尔表达式创建新的作用域;相反,当 shell 计算表达式时,它携带这些表达式的变量绑定,在这种情况下,andalso 右侧的绑定在评估后被删除,而左侧的绑定被保留。我认为这是一个 shell 错误。
  • 也许这也是erl_eval 中的一个错误。 Its code for handling andalso 显示了如何删除评估 andalso 第二部分的绑定(第 452 行),并且只保留第一部分的绑定。如果保留第 2 部分的绑定并在第 457 行与Bs1 合并,那么我的true andalso (Two=2) 示例会在Two 的shell 中添加绑定,但它仍然不能修复涉及的原始案例f(One)。我认为外壳需要一些额外的特殊处理。
  • 那么也许这根本不是一个错误,因为我在之前的评论中提到的不安全变量问题导致编译器正确地拒绝编译这样的构造。
  • @Pascal:我也得出结论,这不是错误。但是尝试(Three=3) + (Four=4)`,它在 shell 中会导致两个变量的新绑定。这是由于erl_eval 处理不同运算符的方式所致;对于+ 运算符和其他运算符,它在执行操作后合并来自两侧的绑定。更改andalsoorelse 也很容易做到这一点,但就像我之前所说的,它仍然不会改变f(One) 案例的情况。另外,请注意您的ok == f(One)andalso 不同,因为它与+ 一样,它合并了== 两侧的绑定。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 2019-04-02
  • 1970-01-01
  • 2014-08-26
相关资源
最近更新 更多