Рубиновое логическое соглашение о двойном отрицании - PullRequest
16 голосов
/ 27 апреля 2011

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

!!(boolean expression)

Ответы [ 3 ]

22 голосов
/ 27 апреля 2011

Двойное отрицание гарантирует, что независимо от начального значения, вы всегда получите true или false, а не какое-либо загадочное значение.

Это удобно, поскольку позволяет избежать висячих ссылок на объекты, которые вы больше нетребуют или должны различать два типа ложных значений: nil и false.

Часто вы увидите методы, написанные так:

def logged_in?
  !!@session_user
end

Это вернет true или false, и это значение может использоваться для любых целей.Сравните это с этим:

def logged_in?
  @session_user
end

В этом случае, если вы сохраняете значение, вы фактически сохраняете весь объект @session_user, который может быть довольно значительным фрагментом памяти.Эта память не может быть освобождена, пока ваша ссылка на нее не выйдет из области видимости.Поскольку существует только один true и один false, сборка мусора не требуется.

3 голосов
/ 27 апреля 2011

Предположим, вы хотите определить метод, который возвращает логическое значение. Например, соответствует ли строка регулярному выражению.

class String
  def include? regex; self =~ regex end
end

Если вы сделаете выше, он вернет nil, если он не совпадает, и целое число, если он совпадает. Во многих случаях это не имеет большого значения (nil аналогично false и true может быть заменено целым числом). Но если вы действительно хотите логическое значение в качестве возвращаемого значения, если вы делаете

class String
  def include? regex; !!(self =~ regex) end
end

он вернет true, когда совпадет, false, если не совпадет.

1 голос
/ 16 июня 2012

На мой взгляд, Ruby слишком умён в отношении логических выражений. Это обходной путь для случаев, когда ум вызывает проблемы.

Вот излишний ум: нет логического класса. Вместо этого существует соглашение, согласно которому любое значение может служить логическим значением. В контексте, где требуется значение true-or-false, nil или false означает «false», а все остальное означает «true». Значения true и false не являются частью специального класса, они являются единственными членами своих классов & mdash; они существуют только для того, чтобы сделать код немного более читабельным.

Я думаю, что это работает нормально большую часть времени, но время от времени вам нужно логическое значение, которое всегда true или false. Например, недавно мне нужно было сравнить два логических значения и сделать что-то особенное, если они различны; Единственная проблема в том, что один из них был либо true, либо false, а другой - 1 или nil. Фикс? Используйте тот факт, что !!nil == false и !!1 == true.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...