Смотрите этот простой класс 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 - она уже знает, что будет локальная переменная bar, определенная в строке #10, которая затеняет метод bar, а отладчик на самом деле не возможно больше, чтобы вызвать метод bar. На данный момент не известно, что строка 'local string' будет назначаться bar. Отладчик возвращает nil для bar.
Продолжим исходный код в файле Ruby и посмотрим на его вывод:
(byebug) continue
method
"string from method"
local-variable
"local string"
Во время выполнения в строке #7 Ruby все еще знает, что bar действительно является методом, и он все еще может вызвать его в строке #8. Тогда l ine #10 фактически определяет локальную переменную, которая затеняет метод с тем же именем, и поэтому Ruby возвращается, как ожидается, в строке #12 и #13.
Вопросы: Почему отладчик возвращает разные значения, чем исходный код? Похоже, он способен заглянуть в будущее. Это считается признаком или ошибкой? Описан ли это поведение?