新的IRB会话如何获得其变量范围?

Nat*_*ong 2 ruby scope irb

IRB是一种在Ruby中进行游戏和测试的好方法.也可以使用脚本进行一些设置,如下所示:

require 'irb'

class Pirate
  def greet
    puts "Arrrrr, nice to meet ya"
  end
end

IRB.start # You can now instantiate Pirate in IRB
Run Code Online (Sandbox Code Playgroud)

然而,我不清楚的一件事是这样做的范围可变.如果我之前添加这些行IRB.start:

smithy     = Pirate.new
@blackbard = Pirate.new
Run Code Online (Sandbox Code Playgroud)

... @blackbeard将在IRB中提供,但参考smithy将得到undefined local variable or method 'smithy' for main:Object.

为什么?

Nik*_* B. 6

Binding用来评价代码是建立在irb/workspace.rb:51(我指的是红宝石1.9.3修订版35410这里):

@binding = eval("def irb_binding; binding; end; irb_binding",
                TOPLEVEL_BINDING,
                __FILE__,
                __LINE__ - 3)
Run Code Online (Sandbox Code Playgroud)

这意味着您的IRB会话在与顶级方法内的代码相同的上下文中运行.注意:

puts "Outer object ID: %d" % self.object_id
puts "Outer binding: " + binding.inspect
smithy     = Pirate.new
@blackbard = Pirate.new

def test
  puts "Inner object ID: %d" % self.object_id
  puts "Inner binding: " + binding.inspect
  p @blackbard
  p smithy
end
test
Run Code Online (Sandbox Code Playgroud)

输出:

Outer object ID: 13230960
Outer binding: #<Binding:0x00000001c9aee0>
Inner object ID: 13230960
Inner binding: #<Binding:0x00000001c9acd8>
#<Pirate:0x00000001c9ada0>
/test.rb:18:in `test': undefined local variable or method `smithy' for main:Object (NameError)
    ...
Run Code Online (Sandbox Code Playgroud)

请注意,对象context(self)在函数内部和外部都是相同的.这是因为每个顶级方法都添加到全局main对象中.

另请注意,方法内部和外部的绑定不同.在Ruby中,每个方法都有自己的名称范围.这就是您无法从IRB内部访问本地名称的原因,同时您可以访问实例变量.

说实话,IRB并不是Ruby软件中最辉煌的一部分.我通常使用Pry来做这种东西,使用它你可以做到:

require 'pry'
binding.pry
Run Code Online (Sandbox Code Playgroud)

并且有一个会话可以访问当前的局部变量.