В Ruby для неопределенной переменной "foo", почему "foo = foo" не вызывает ошибку? - PullRequest
8 голосов
/ 10 июля 2019

Когда foo является неопределенной переменной, попытка доступа к ней вызывает NameError:

foo
#=> NameError: undefined local variable or method `foo'

a = foo
#=> NameError: undefined local variable or method `foo'

Почему foo = foo не поднимает NameError?

foo = foo
#=> nil

Вчера мне потребовались часы, чтобы отследить эту строку как ошибку в программе ...

capture = capture.to_i

То, что я намеревался сделать, это преобразовать capture_str в Integer. Вместо этого я ввел nil, сказав capture = capture, а затем превратив этот ноль в 0. Итак, я делал это ...

capture = capture.to_i
#=> 0

Но я ошибочно полагал, что переменная NameError была бы выброшена, как это ...

capture = capture_str.to_i
#=> NameError: undefined local variable or method `capture_str'

1 Ответ

14 голосов
/ 10 июля 2019

В Ruby есть такая странная функция , что он поднимает переменные, когда они объявлены:

Это означает, что когда синтаксический анализатор видит x = 1, он фактически объявляет переменную, присваивая ей значение nil и позволяя интерпретатору выяснить, будет ли когда-либо выполняться строка x = 1.

источник

Итак, когда вы пишете

a = a.to_i

сначала он объявляет a = nil, затем вызывает to_i и присваивает:

a = nil
a = a.to_i

EDIT:

Это также работает в других случаях, например с if:

pry> b
NameError: undefined local variable or method `b' for main:Object
from (pry):30:in `__pry__'
pry> b if b.nil?
NameError: undefined local variable or method `b' for main:Object
from (pry):31:in `__pry__'
pry> b = 1 if b.nil?
#=> 1
pry> b
#=> 1

и (пример из ссылки на блог):

if false
  x = 1
end
puts x.class
# NilClass
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...