Странное поведение с определением Ruby? - PullRequest
0 голосов
/ 30 января 2019

Я новичок в Ruby и у меня есть вопрос с определенным?Ключевое слово.

Вот фрагмент кода, который я написал для загрузки файла yaml для инициализации настроек в моем скрипте Ruby:

# Read settings file
require 'YAML'
settingsFile = File.join(File.dirname(__FILE__), "settings.yml").tr('\\', '/')
Settings = YAML.load_file(settingsFile) unless defined? Settings
puts Settings

Файл yaml выглядит следующим образом:

Hello: World

Это выводит правильно с:

{"Hello" => "world"}

Теперь, если я использую переменную вместо константы длясохранить настройки, такие как:

# Read settings file
require 'YAML'
settingsFile = File.join(File.dirname(__FILE__), "settings.yml").tr('\\', '/')
settings = YAML.load_file(settingsFile) unless defined? settings
puts settings

настройки возвращаются пустыми.

Что дает?Почему бы с помощью константы сделать эту работу?

1 Ответ

0 голосов
/ 30 января 2019

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...