2016-01-12 7 views
4

Я читаю через программирование Ruby, Руководство прагматического программиста (кирка Book), автор утверждает, что есть разница между:Разница между a = a || б и || = б

var = var || "Default Value" 

и:

var || = "Default Value" 

Я не понимаю этого, поскольку нет никакой разницы с тем, что я вижу. Кто-нибудь может мне с этим помочь?

+1

Насколько я знаю, два выражения будут иметь одинаковый результат для любого значения 'var'? Не могли бы вы добавить цитату из книги на свой вопрос, чтобы указать, что означает автор? :-) – Drenmi

+0

Я думаю, что это всего лишь два способа написать одно и то же выражение. – Atri

+0

Вы, ребята, классные. Спасибо – gates

ответ

3

Цитирование ресурс here:

В A = A || b, a задается чем-то по инструкции на каждом прогоне, , тогда как с || a = b, a устанавливается только в том случае, если a логически ложно (т. е. , если оно равно нулю или false), поскольку || «короткое замыкание». То есть, если с левой стороны от || сравнение верно, нет необходимости в проверить правую сторону.

Это в основном означает, что они будут вести себя аналогично вам, разработчику, но внутренне реализации отличаются, как объяснялось выше.

EDIT: Как указано в комментариях, выше объяснение считает a || a = b вместо a ||= b. Очень хорошая точка и прочтение этой же ссылки поясняет следующее:

Если a не определено, то || a = 42 вызывает NameError, а значение || = 42 возвращает 42. Таким образом, они не кажутся эквивалентными выражениями.

Итак, опять же, они не то же самое утверждение, потому что Руби выделяет переменную в тот момент он видит назначение на синтаксического анализа времени (которое в случае a ||= 42).

Один последняя цитата, так что вы не думаете, что я выдумываю, :)

Рубина видит назначение на этапе синтаксического разбора и создает переменную таким образом, что он не будет с a || a = 42, даже если он заканчивается , который ведет себя как последний после фактического выполнения.

+2

Это то, что OP имеет в виду, хотя? В вопросе указывается различие между «a = a || b' и 'a || = b', а не' a = a || b' и 'a || a = b'? – Drenmi

+1

@Drenmi: 'a || = b' является ярлыком для' a || a = b'. (_i.e. присваивание пропускается в случае, если 'a' не' nil' или 'false'_) – potashin

+0

Да, даже я не получаю || = b - это || a = b, вы можете объяснить? @potashin – gates

3

Разница становится более очевидной, если вы используете класс с геттер и сеттер:

class Foo 
    def var 
    puts 'Foo#var called' 
    @var 
    end 
    def var=(value) 
    puts 'Foo#var= called' 
    @var = value 
    end 
end 

Ваш первый пример приводит к Foo#var= называют очень много времени:

f = Foo.new 
f.var = f.var || "Default Value" 
# Foo#var called 
# Foo#var= called 
f.var = f.var || "Default Value" 
# Foo#var called 
# Foo#var= called 

Если в вашей второй Например, Foo#var= вызывается только один раз:

f = Foo.new 
f.var ||= "Default Value" 
# Foo#var called 
# Foo#var= called 
f.var ||= "Default Value" 
# Foo#var called 
+0

Почему 'Foo.var' не был вызван второй раз во втором случае? –

+1

@WandMaker '|| =' выполняет присвоение только в том случае, если значение левой руки было 'nil' или' false'. 'f.var' изначально' nil', поэтому первый 'f.var || =' присваивает '' значение по умолчанию ''. Во второй раз 'f.var' возвращает' 'значение по умолчанию '', поэтому никакое присвоение не выполняется. – Stefan

+1

Если я не ошибаюсь, эквивалентное выражение будет выглядеть как 'f.var.tap {| v | f.var = v || 'Значение по умолчанию', если v} ' – Stefan

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