Просто интересно, что !!
находится в Ruby.
Что значит!! означает в рубине?
Ответ 1
Не. Он использовался для преобразования значения в логическое значение:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
Обычно использовать это не нужно, поскольку единственные ложные значения для Ruby - это nil
и false
, поэтому обычно лучше разрешить это соглашение.
Подумайте об этом как
!(!some_val)
Одна вещь, которая используется для законного действия, - это предотвращение возврата огромного куска данных. Например, вы, вероятно, не хотите возвращать 3MB данных изображения в свой метод has_image?
, или вы можете не захотеть вернуть весь объект пользователя в методе logged_in?
. Использование !!
преобразует эти объекты в простой true
/false
.
Ответ 2
Он возвращает true
, если объект справа не nil
, а не false
, false
, если он nil
или false
def logged_in?
[email protected]_user
end
Ответ 3
!
означает отрицание логического состояния, два !
ничего особенного, кроме двойного отрицания.
!true == false
# => true
Обычно используется, чтобы заставить метод возвращать логическое значение. Он обнаружит любую правду, такую как строка, целые числа, а что нет, и превратит ее в логическое.
!"wtf"
# => false
!!"wtf"
# => true
Более реальный вариант использования:
def title
"I return a string."
end
def title_exists?
!!title
end
Это полезно, когда вы хотите убедиться, что возвращается логическое значение. ИМХО, это довольно бессмысленно, хотя, видя, что оба if 'some string'
и if true
- это тот же поток, но некоторые люди считают полезным возвращать логическое значение.
Ответ 4
Обратите внимание, что эта идиома существует и на других языках программирования. C не имел встроенного типа bool
, поэтому все булевы были введены как int
, а канонические значения 0
или 1
. Делает этот пример (скобки добавлены для ясности):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
Синтаксис "не-не" преобразует любое ненулевое целое число в 1
, каноническое логическое истинное значение.
В общем, я считаю гораздо лучше провести разумное сравнение, чем использовать эту необычную идиому:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
Ответ 5
Это полезно, если вам нужно сделать эксклюзивную или. Копирование с Мэтта ван Хорна отвечает небольшими изменениями:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
Я использовал его для обеспечения того, чтобы две переменные имели либо нуль, либо оба не ноль.
raise "Inconsistency" if !!a ^ !!b
Ответ 6
Это "двойной отрицательный", но практика не поощряется. Если вы используете rubocop, вы увидите, что он жалуется на такой код с нарушением Style/DoubleNegation
.
В аргументе говорится:
Поскольку это и загадочно и обычно избыточно, его следует избегать [затем перефразировать:] Измените
!!something
на!something.nil?
Ответ 7
Понимание того, как это работает, может быть полезно, если вам нужно преобразовать, скажем, перечисление в логическое. У меня есть код, который делает именно это, используя classy_enum
gem:
class LinkStatus < ClassyEnum::Base
def !
return true
end
end
class LinkStatus::No < LinkStatus
end
class LinkStatus::Claimed < LinkStatus
def !
return false
end
end
class LinkStatus::Confirmed < LinkStatus
def !
return false
end
end
class LinkStatus::Denied < LinkStatus
end
Тогда в служебном коде у меня есть, например:
raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states.
Фактически оператор bangbang стал тем, что я мог бы написать в качестве метода, называемого to_bool.