2014-01-17 1 views
1

Это что-то странное, что я выяснил в ruby ​​1.9.3.Переменная в другом состоянии принятое значение nil

Вот код:

>> r = true 
>> if r 
>> a = "hello" 
>> else 
>> b = "hello" 
>> end 

Теперь значение a является "привет":

>> a 
=> "hello" 

И странно значение b равна нулю

>> b 
=> nil 

Поскольку b нигде в сцене, он должен быть необъявлен.

Почему?

ответ

2

Локальная переменная создается, когда анализатор встречает назначение, а не когда происходит назначение:

=> foo 
# NameError: undefined local variable or method `foo' for main:Object 
=> if false 
=> foo = "bar" # does not assign to foo 
=> end 
=> nil 
=> foo 
=> nil 
+0

Не инициализируется. Вот почему он оценивает 'nil'. –

3

Объявления переменных вступают в силу, даже если ветвь, где выполняется присвоение, никогда не достигается.

+0

@Patritosh: Я просто побежал ваш код, а затем побежал 'путы b.object_id # => 70364348734500'. Как вы видите, объект 'b' был создан и задан значение' nil'. –

+2

@CarySwoveland: Это странно. Какую версию Ruby вы используете? Это не требуется спецификацией, но на всех даже отдаленно популярных реализациях Ruby (MRI, YARV, Rubinius, JRuby, IronRuby, MRuby, Ruby.NET, XRuby, MagLev, MacRuby, Cardinal, Topaz, BlueRuby, Ruby GoLightly, tinyrb), 'object_id'' nil' - '4'. –

+0

@ Jörg, странно! Это должно быть 'b.object_id # => 8'. (Я использую MRI 2.0.0). Итак, как я получил 70364348734500? Это был IRB. Я использовал переменную 'b', чтобы проверить что-то еще раньше, и пренебречь, чтобы проверить ее значение после запуска кода афера, и' puts b.object_id'. Почему я не заметил, что что-то не так? Никаких объяснений этому нет. 'object_id' из' nil' был [изменен на 8] (http://stackoverflow.com/questions/15506763/why-was-the-object-id-for-true-and-nil-changed-in-ruby2- 0) в 2.0. –

3

Причина этого объясняется в Ruby documentation, и это справедливо для любого версия Ruby, а не только 1,9:

локальная переменная создается, когда анализатор встречает назначение, нет, когда выполняется присвоение.

Это означает, что если анализатор видит назначение в коде, он создает локальную переменную, даже если присваивание никогда не произойдет. В этом случае величина, на которую ссылается переменная является nil:

if true 
    a = 0 
else 
    b = 0 
end 

p local_variables 
# => [:a, :b] 

p a 
# => 0 

p b 
# => nil