【发布时间】:2017-03-09 13:53:07
【问题描述】:
查看这个简单的 Ruby 类:
require 'byebug'
class Foo
def run
byebug
puts defined?(bar)
puts bar.inspect
bar = 'local string'
puts defined?(bar)
puts bar.inspect
end
def bar
'string from method'
end
end
Foo.new.run
在运行此类时,可以在调试器的控制台中观察到以下行为:
$ ruby byebug.rb
[2, 11] in /../test.rb
2:
3: class Foo
4: def run
5: byebug
6:
=> 7: puts defined?(bar)
8: puts bar.inspect
9:
10: bar = 'local string'
11:
调试器在断点处返回以下值:
(byebug) defined?(bar)
"local-variable"
(byebug) bar.inspect
"nil"
请注意——尽管调试器的断点在#5 行——它已经知道在#10 行中定义了一个局部变量bar,它会影响bar 方法,而调试器实际上不是能够再调用bar 方法。目前不知道的是字符串'local string' 将被分配给bar。调试器为bar 返回nil。
让我们继续 Ruby 文件中的原始代码并查看其输出:
(byebug) continue
method
"string from method"
local-variable
"local string"
在运行时#7 行中,Ruby 仍然知道bar 确实是一个方法,并且它仍然能够在行#8 中调用它。然后行 #10 实际上定义了隐藏具有相同名称的方法的局部变量,并且 tTherefore Ruby 在行 #12 和 #13 中返回预期的那样。
问题:为什么调试器返回的值与原始代码不同?它似乎能够展望未来。这被认为是功能还是错误?是否记录了这种行为?
【问题讨论】:
-
我不会说它是 Ruby,而是
byebug。如果在赋值之前和之后将其包装在rescue NoMethodError和puts defined?(bar)中,您会看到该行之前是"method",之后是"local-variable"。 -
@Stefan,我虽然也一样,但事实并非如此。如果您在两者之间单独放置另一条执行某项操作的语句,您仍然会得到相同的结果。
-
@Stefan:是的,有。拿起一份“显微镜下的红宝石”
-
@SergioTulentsev 书明天到货,谢谢! :-)
-
@ndn: 好久没看它了,但我记得它以最详细的方式描述了方法解析和执行。下到操作码。 :)
标签: ruby debugging binding byebug