【问题标题】:Lambda local variable default value fails to use the closured local variableLambda 局部变量默认值无法使用封闭的局部变量
【发布时间】:2016-12-28 17:57:00
【问题描述】:

考虑以下代码:

x = 1
λ = ->(x = x) { puts "[#{x}]"; x = 2; puts "[#{x}]" }

我希望 最顶层的局部变量 x 将用作 lambda 的局部变量 x 的默认值。也就是说,上面的代码应该或多或少等同于:

λ = ->(x = 1) { puts "[#{x}]"; x = 2; puts "[#{x}]" }

不幸的是,情况并非如此:(x = x) 没有被这样处理,而 lambda 的本地 x 最初被设置为 nil

λ.()
#⇒ []
#  [2]

为什么(x = x) 中的 RHO 不是取自最外层的binding

【问题讨论】:

  • 对于它的价值,如果您在应用程序中需要它,您可以使用-> (x = nil) { x = x || default; ... } 其中default 是您希望用作默认值的块外、范围内的局部变量.
  • @coreyward 我没有问如何克服这个问题,->(x = default) { ... } 就足够了。我问为什么 RHO 没有得到应有的对待。
  • 抱怨行为“没有得到应有的对待”不在 Stack Overflow 的范围内,它旨在帮助解决实际的、非假设的编程问题。根据语言创建者,这是 Ruby 中的预期行为。
  • @coreyward 这是一个实际的、非假设的问题。如果不理解,不代表问题不存在。没有任何一种语言的 RHO 会以这种方式运行。答案“x = x 代码优先于常识,并且总是解析为 x = nil,尽管有范围”会很好(尽管有点令人沮丧。)

标签: ruby lambda proc


【解决方案1】:
λ = ->(x = x) {…}

在上面的代码中,x 参数标识符覆盖了当前作用域的同名局部变量,所以默认值已经引用了这个参数,而不是原始的 x

对于默认值,您可以使用不同的局部变量名称、实例变量,或者如果坚持使用外部 xBinding#local_variable_get

【讨论】:

  • @mudasobwa 你是认真的吗?你在说什么废话?在 Ruby 2.2 或更新版本中,您甚至会收到警告 circular argument reference - x。有关详细信息,请参阅bugreport #10314。它证实了我所写的。
  • 1.它被称为“范围”,与“命名空间”无关,通常指的是Module 嵌套。 2. 方法确实引入了新的作用域,而procs/lambdas 没有;试试:x = 1; λ = ->(y = x) { puts local_variables }。 3.在y = x中,x是一个RHO,必须由最外层作用域解析。 4. 我不知道,为什么 Matz 认为这种行为是可以的,但是很好,MINSWAN。
  • 对不起,这是吹毛求疵的词。要点仍然存在 - 参数定义掩盖了局部变量。我会用正确的术语来修正答案。
  • 另外,您链接的错误与我的问题有点关系:这是方法的重大变化; lambda 总是以这种方式表现。也就是说,在2.1.10 中,def x; 1; end; def foo(x = x); puts x; end; foo 成功打印了1,而我的示例仍然失败。
  • 如果Binding#local_variable_get 可以工作,x = x 也确实可以工作。显然存在三种不同的绑定,一种在外部范围内,一种在块参数定义内(原文如此!),一种在块本身内。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多