ruby - 为什么即使未执行该代码路径,Ruby 似乎也会从 case 语句内部提升变量声明?

标签 ruby

<分区>

我们定义一个函数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 也是如此。

这是另一个类似的例子:

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 提升”只会出现有关 JavaScript 提升的结果。)

最佳答案

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

x = 1

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

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 variables 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 - 为什么即使未执行该代码路径,Ruby 似乎也会从 case 语句内部提升变量声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12928050/

相关文章:

ruby - IntelliJ IDEA 12 不会在 rails/ruby 的断点处停止

ruby - Mavericks 的 Pg gem : NameError: uninitialized constant PG

ruby - 使用 each 和 map 修改数组索引的范围

ruby - 交互式 ruby​​ 控制台 (irb) 是否有快捷方式?

ruby-on-rails - Rails 需要 RubyGems >= 0.9.4。请安装 RubyGems

ruby 混合 : extend or include?

ruby-on-rails - rubymine 错误 - 无法在任何来源中找到 capybara-webkit-0.9.0

ruby-on-rails - 无法检测 rake 任务 - Errno::ENOENT: 没有这样的文件或目录 - R

ruby - 为什么哈希字面量在 Ruby 中被称为哈希字面量?

ruby-on-rails - HTTPBadRequest {"error_description": "Code has expired", "error": "invalid_grant"} for Oauth authentification, Rails 上的 ruby