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

时间:2012-05-26 15:13:20

标签: 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

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

smithy     = Pirate.new
@blackbard = Pirate.new

... @blackbeard将在IRB中提供,但引用smithy将获得undefined local variable or method 'smithy' for main:Object

为什么?

1 个答案:

答案 0 :(得分:6)

用于评估代码的Bindingirb/workspace.rb:51中设置(我在这里指的是Ruby 1.9.3 rev 35410):

@binding = eval("def irb_binding; binding; end; irb_binding",
                TOPLEVEL_BINDING,
                __FILE__,
                __LINE__ - 3)

这意味着您的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

输出:

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)
    ...

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

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

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

require 'pry'
binding.pry

并且可以访问当前本地变量。