Что значит!! означает в рубине?

Просто интересно, что !! находится в 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.