为什么变量只在未执行的Ruby代码中出现时才被"定义"?

Pet*_*vin 1 ruby

下面的Ruby代码会导致x被"定义"(即defined(x)返回"local-variable"哪怕是这个代码的执行之前,而且即使不进行分配未定义:

如果为假,则x = 1

具体来说,x局部变量将设置为nil.对于从未执行过的赋值while falseuntil false子句的赋值,行为类似.您可以在irb中运行或在某些代码片段上运行ruby来验证这一点.

我的问题是双重的:

  1. 这种行为记录在哪里吗?
  2. 在任何地方都记录了这种行为的理由吗?

Ama*_*dan 6

以下是编译器的一些见解.这是Ruby 2.0.0转换x = 1 if false; puts x; puts y为(在执行任何代码之前):

== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
local table (size: 2, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 2] x          
0000 trace            1                                               (   1)
0002 jump             7
0004 putobject_OP_INT2FIX_O_1_C_ 
0005 setlocal_OP__WC__0 2
0007 trace            1
0009 putself          
0010 getlocal_OP__WC__0 2
0012 opt_send_simple  <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP>
0014 pop              
0015 trace            1
0017 putself          
0018 putself          
0019 opt_send_simple  <callinfo!mid:y, argc:0, FCALL|VCALL|ARGS_SKIP>
0021 opt_send_simple  <callinfo!mid:puts, argc:1, FCALL|ARGS_SKIP>
0023 leave          
Run Code Online (Sandbox Code Playgroud)

您可以看到本地表将其槽分配2给局部变量x.分配本身(putobject,setlocal 2)被跳过jump 7.puts x因此取出插槽2和电话puts; 但是,既然y在这个范围或更高的范围内都没有被认为是局部变量,那么它被认为可能是一种方法,实际上,几乎就像你写的一样puts(y()).在执行时,y无法解决,并引发错误.