Двойной амперсанд в Ruby

Я использую authlogic драгоценный камень с Ruby on Rails, и я использовал следующее для получения идентификатора пользователя, который в настоящее время зарегистрирован:

current_user = UserSession.find
id = current_user && current_user.record.id

Я не понимаю, как current_user && current_user.record.id возвращает текущий идентификатор пользователя. Я думал бы, что это возвратит булевскую переменную. Кто-то может объяснить, как это работает?

7
задан Chad Johnson 1 January 2010 в 05:30
поделиться

2 ответа

Логическое и короткое замыкание. Это значит, что если конструкция X &&Y, и X ложна, то Y никогда не проверяется, так как все это, конечно, будет ложным.

Этот код, по сути, говорит:

if (current_user is TRUE) {
    id = current_user.record.id;
]

Вот консольный вывод, показывающий, что вы получаете второе значение, если первое истинно:

irb(main):005:0> true && 9
=> 9

и ноль, если первое равно нулю:

irb(main):008:0> nil && 9
=> nil
9
ответ дан 6 December 2019 в 06:24
поделиться

В Ruby нет типа Boolean; Ruby имеет довольно простой взгляд на истину (или, точнее, довольно простой взгляд на ложь).

  • объект false, который является однотонным экземпляром FalseClass, считается фальшивым
  • объектом nil, который является однотонным экземпляром NilClass - это фальшивка
  • каждый другой объект - это Truthy (включая, очевидно, true объект, который является однотонным экземпляром TrueClass)
  • .

[BTW: это означает, что многие объекты, которые считаются фальшивыми в некоторых других языках, на самом деле являются правдивыми в Ruby, как и целое число 0, вещественное значение 0. 0, пустая строка, пустой массив, пустой хэш, символ 'F']

Итак, булевы операторы &&, ||, и и или не возвращают булевых значений. Вместо этого они возвращают первый объект, определяющий результат выражения.

(Они также являются короткими замыканиями, что означает, что они оценивают только минимальные подвыражения, необходимые для определения результата выражения. Таким образом, альтернативная формулировка будет состоять в том, что они возвращают результат последнего вычисления, которое было оценено. Что, в свою очередь, аналогично тому, что делают блоки, методы, тела классов и модульные тела)

Итак, что значит вернуть первый объект, определяющий результат? Это просто, на самом деле: результатом выражения

 a && b

является правда , если и a, и b являются b, в противном случае это фальшивка . Таким образом, если a является фальшивкой , то полностью не имеет значения, что такое b: в любом случае результат будет фальшивкой . Таким образом, мы можем просто вернуть a. (Помните, a не обязательно должно быть false, она также может быть nil, и программист может захотеть узнать, какая из них была.)

Если, ОТОХ, a является truthy (IOW оно не является ни nil, ни false), тогда результат всего выражения является исключительно зависимым от b: если b является правдивым, то весь результат будет правдивым, в противном случае, если b является фальшивым, то весь результат будет фальшивым. Таким образом, мы могли бы с тем же успехом вернуть b самому себе, вместо того, чтобы сначала преобразовать его в булев.

|| и или аналогичны или точнее двойные в && и и .

Вы разместили этот пример:

id = current_user && current_user.record.id

Здесь автор даже не ожидает что current_user будет булевым значением! Вместо этого он ожидает, что это будет либо User, либо nil. Но это совершенно нормально, потому что User - это truthy, а nil - это falsy, так что они все еще могут быть использованы в булевом выражении.

Основное намерение состоит в том, что автор хочет предотвратить поднятие исключения NoMethodError, если он попытается вызвать #ord на nil.

Альтернативным способом выражения этого было бы

id = current_user.record.id unless current_user.nil?

Если вы хотите получить все кровавые детали, обратитесь к разделу 11.1 (стр. 36) проекта спецификации ISO Ruby или к оправдательным спецификациям проекта RubySpec . (Вот однажды я написал для &&.)

Я написал чистую реализацию булевых операторов и условных выражений Рубина один раз для забавы. Множество реализаций - это две микшины.

.
19
ответ дан 6 December 2019 в 06:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: