Это особенность способа, которым Ruby обрабатывает конечные условия if
/ unless
и как переменные возникают и становятся «определенными».
В первом случае константа «не определена»пока ему не присвоено значение.Единственный способ создать константу - это сказать:
CONSTANT = :value
Переменные ведут себя по-разному, и некоторые могут поспорить намного более странно .Они появляются, если они используются где-либо в области видимости, даже в блоках кода, которые пропускаются из-за логических условий.
В случае вашей строки вида:
variable = :value unless defined?(variable)
variable
становится «определенным», так как он существует в самой выполняемой строке, ему будет назначено условие.Чтобы это произошло, это должна быть локальная переменная.
Если вы переделываете это следующим образом:
unless defined?(variable)
variable = :value
end
Тогда поведение исчезает, присваивание продолжается, поскольку переменная не была определена доэта строка.
Что странно, это:
if defined?(variable)
variable = :value
end
Теперь, очевидно, это не определено, оно не назначено, но тогда это происходит:
defined?(variable)
# => "local-variable"
Теперь он все равно определен, потому что Руби уверен, что это переменная.У него еще нет значения, оно nil
, но оно "определено" для Руби.
Становится еще более странным:
defined?(variable)
# => false
if (false)
variable = :value
end
defined?(variable)
# => "local-variable"
Где этот блок кодадаже не бежал, он не может даже бегать, и все же, вот, variable
теперь определено.Начиная с этой строки присваивания эта переменная существует в отношении Ruby.
Поскольку вы выполняете попытку присваивания и defined?
в той же строке, переменная существует и ваше присваиваниене случитсяЭто похоже на крошечный парадокс.