Символы с двойной трубкой в задании переменной Ruby?
Возможный дубликат:
Что означает || = в Ruby?
Простите меня, если это новый вопрос, но я читаю книгу о рельсах, где автор использовал это выражение в вспомогательном методе:
@current_user ||= User.find_by_id(session[:user_id])
Является ли это использование двойных каналов еще логическим оператором OR?
Если да, то как это работает?
Ответы
Ответ 1
Это условное задание. Из здесь:
x = find_something() #=>nil
x ||= "default" #=>"default" : value of x will be replaced with "default", but only if x is nil or false
x ||= "other" #=>"default" : value of x is not replaced if it already is other than nil or false
Ответ 2
Код foo ||= bar
почти эквивалентен foo = foo || bar
. В Ruby (как на многих языках, таких как JavaScript или Io) логические операторы являются "защитными" операторами. Вместо того, чтобы всегда возвращать true
или false
, они вычисляют значение первого операнда, который оценивает "правдивое" значение.
Например, этот код foo = 1 || delete_all_files_from_my_computer()
ничего не удалит: foo будет установлен в 1
, а второй операнд даже не будет оценен.
В Ruby единственными значениями "неправды" являются nil
и false
. Таким образом, код foo ||= bar
будет оценивать только bar
и устанавливать foo
на результат, если foo
равен nil
или false
.
В качестве переменных экземпляра по умолчанию используется nil
, если он не установлен, код типа @foo ||= bar
является обычной идикой Ruby для установки переменной экземпляра, если она еще не была установлена.
Ответ 3
Вы можете думать об этом как о сокращении:
@current_user = @current_user || User.find_by_id(session[:user_id])
@current_user
оценивается первым, если оно не равно нулю, то замыкается ИЛИ, возвращая значение @current_user и не вызывая User.find_by_id.
(Это работает только потому, что Ruby рассматривает null как false и ненулевое как true в логическом контексте. Он не работает для языков, таких как Java, которые не рассматривают non-booleans как истинные.)