为什么即使没有执行该代码路径,Ruby 似乎也会从 case 语句内部提升变量声明? [英] Why does Ruby seem to hoist variable declarations from inside a case statement even if that code path is not executed?

查看:39
本文介绍了为什么即使没有执行该代码路径,Ruby 似乎也会从 case 语句内部提升变量声明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们定义了一个函数foo:

We define a function foo:

def foo(s)
  case s
  when'foo'
    x = 3
    puts x.inspect
  when 'bar'
    y = 4
    puts y.inspect
  end
  puts x.inspect
  puts y.inspect
end

然后我们这样称呼它:

1.9.3p194 :017 > foo('foo')
in foo scope
3
in outer scope
3
nil
 => nil 

1.9.3p194 :018 > foo('bar')
in bar scope
3
in outer scope
nil
3
 => nil 

为什么函数在任何一种情况下都不会抛出有关未注册局部变量的错误?在第一种情况下,变量 y 似乎不应该存在,因此您不能在外部范围内对其调用 inspect ;第二种情况下 x 相同.

Why does the function not throw an error about an unregistered local variable in either case? In the first case, the variable y seems like it should not exist, so you can't call inspect on it in the outer scope; the same for x in the second case.

这是另一个类似的例子:

Here's another similar example:

def test1
  x = 5 if false
  puts x.inspect
end

def test2
  puts x.inspect
end

然后:

1.9.3p194 :028 > test1
nil
 => nil 

1.9.3p194 :029 > test2
NameError: undefined local variable or method `x' for main:Object

这是怎么回事?Ruby 似乎将变量声明提升到外部作用域,但我不知道这是 Ruby 所做的事情.(搜索ruby hoisting"只会出现关于 JavaScript hoisting 的结果.)

What's going on here? It seems like Ruby is hoisting the variable declaration into the outer scope, but I wasn't aware that this is something Ruby does. (Searching for "ruby hoisting" only turns up results about JavaScript hoisting.)

推荐答案

当 Ruby 解析器看到序列标识符、等号、值、就像在这个表达式中

When the Ruby parser sees the sequence identifier, equal-sign, value, as in this expression

x = 1

它为名为 x 的局部变量分配空间.的创建变量——不是给它赋值,而是内部的变量的创建——总是作为这种类型的结果发生表达式,即使代码没有执行!考虑这个例子:

it allocates space for a local variable called x. The creation of the variable—not the assignment of a value to it, but the internal creation of a variable—always takes place as a result of this kind of expression, even if the code isn’t executed! Consider this example:

if false
  x = 1
end
p x # Output: nil
p y # Fatal Error: y is unknown

x 的赋值没有被执行,因为它包含在一个失败的条件测试.但是 Ruby 解析器看到序列 x = 1,来自它推断程序涉及一个局部变量 x.这解析器并不关心 x 是否曾经被赋值过.它的工作是只是为了搜索需要空间的局部变量的代码被分配.结果是 x 处于一种奇怪的可变边缘.已生成并初始化为nil.在这方面,它不同于不存在于全部;正如您在示例中看到的,检查 x 会为您提供值nil,而尝试检查不存在的变量 y 结果在一个致命的错误.但是虽然 x 存在,但它并没有起到任何作用该程序.它仅作为解析过程的工件存在.

The assignment to x isn’t executed, because it’s wrapped in a failing conditional test. But the Ruby parser sees the sequence x = 1, from which it deduces that the program involves a local variable x. The parser doesn’t care whether x is ever assigned a value. Its job is just to scour the code for local vari ables for which space needs to be allocated. The result is that x inhabits a strange kind of variable limbo. It has been brought into being and initialized to nil. In that respect, it differs from a variable that has no existence at all; as you can see in the example, examining x gives you the value nil, whereas trying to inspect the non-existent variable y results in a fatal error. But although x exists, it has not played any role in the program. It exists only as an artifact of the parsing process.

扎实的 Rubyist 第 6.1.2 章

这篇关于为什么即使没有执行该代码路径,Ruby 似乎也会从 case 语句内部提升变量声明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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