2013-08-14 3 views
1

Я думал, что:Положения «если» условие

do_something if condition 

были эквивалентны

if condition 
    do_something 
end 

Я нашел код, который не уважает это правило.

if !(defined? foo) 
    foo = default_value 
end 

Здесь foo принимает default_value.

foo = default_value if !(defined? foo) 

Здесь foo принимает nil. В первом коде, я думаю, if выполняется первым, и должен быть эквивалентен:

foo = (default_value if !(defined? foo)) 

Есть ли способ задать default_value, если переменная не определена?

Общий ответ:

Некоторые несколько замечаний хотят использовать ||= оператор ... Который не будет работать, если foo является nil:

foo ||= default_value 

будет возвращать значение по умолчанию, в то время как foo является определены.

Я настаиваю на использовании «не defined?», который не равен nil.

+0

это опечатка? -> if (определено? foo) # в третьем блоке кода, вызывают в четвертом его -> if! (defined? foo) – ajt

+0

@ajt. Вы правы. Я забыл «!» ... – pierallard

+1

Idiomatic Ruby будет использовать '|| =', вы против этого? –

ответ

3

две части кода эквивалентны синтаксически, но отличаются от с точки зрения разбора. Вы частично правы, что «if выполняется первым», но это касается только синтаксиса. В рамках синтаксического анализа порядок разбора следует линейному порядку жетонов. В Ruby, когда у вас есть задание:

foo = ... 

затем foo назначается nil, даже если эта часть кода не синтаксически оцененную, и это влияет на результат defined?.

Для того, чтобы написать рядный без этой проблемы, как я сделать, это использовать and, or, && или ||:

defined?(foo) or foo = default_value 
+0

Да, я чувствую, что вы понимаете, что я имею в виду. Есть ли красивое письмо для размещения вокруг задания, например {foo = xxx}, если условие? – pierallard

+0

нет, если вы начинаете с foo =, он будет разобран и частично оценен. У вас должно быть условие перед выражением 'foo ='. Даже явный 'begin foo = 5 end if defined (foo)' заставляет foo автоматически определяться. Вероятно, единственным разумным способом является то, что «или» пример, который только что предоставила пила. – quetzalcoatl

+0

'defined? (Foo) или foo = default_value', и одним махом мы сделали Ruby похожим на Perl. :-) –

5

Путь Рубин

foo ||= default_value 

Но, конечно

if (defined? foo) 
    foo = default_value 
end 

и

foo = default_value if !(defined? foo) 

различны. Вы не сравниваете одно и то же.

В одном вы сравните (defined? foo), а другой сравнить !(defined? foo)

Я думаю, что вы действительно после следующих

if !(defined? foo) 
    foo = default_value 
end 
+0

Извините, я забыл '!' В своем первом сообщении ... Это меняет весь контекст этого вопроса. Сожалею. – pierallard

+0

Просто проверьте 2 выражения if (3 строки и 1 строку), в том же контексте! Результат 'foo' после не то же самое ... – pierallard

Смежные вопросы