Смотрите этот простой класс 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
.
Вопросы: Почему отладчик возвращает разные значения, чем исходный код? Похоже, он способен заглянуть в будущее. Это считается признаком или ошибкой? Описан ли это поведение?