Відповіді:
Не так. Він використовується для перетворення значення в булеве:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
Це, як правило , немає необхідності використовувати хоча , так як тільки помилкові значення в рубін nil
і false
, тому , як правило , краще , щоб ця конвенція позиції.
Подумайте про це як
!(!some_val)
Одне, що легітимно використовується, це запобігання поверненню величезних фрагментів даних. Наприклад, ви, ймовірно, не хочете повертати 3MB даних зображень у своєму has_image?
методі, або ви не хочете повертати весь logged_in?
метод об'єкта користувача в методі. Використання !!
перетворює ці об'єкти в простий true
/ false
.
.nil?
замість використання !!
? Чи є різниця?
!!true #=> true
іtrue.nil? #=> false
!
означає заперечення булевого стану, два !
s - це не що інше, крім подвійного заперечення.
!true == false
# => true
Зазвичай він застосовується для примушування методу повернути булеву форму. Він виявить будь-який вид правдивості, такий як рядок, цілі числа і що ні, і перетворить його в булевий.
!"wtf"
# => false
!!"wtf"
# => true
Більш реальний випадок використання:
def title
"I return a string."
end
def title_exists?
!!title
end
Це корисно, коли ви хочете переконатися, що булева інформація повернута. IMHO - це начебто безглуздо, бачачи, що і те, if 'some string'
і if true
те саме такий потік, але деяким людям вважається корисним явно повернути булеву форму.
title
, може також зробити найближче до нього ... Я думаю
Зауважте, що ця ідіома існує і в інших мовах програмування. C не мав внутрішнього bool
типу, тому всі булеві символи були набрані int
натомість із канонічними значеннями 0
або 1
. Візьмемо цей приклад (для чіткості додаються круглі дужки):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
Синтаксис "не-не" перетворює будь-яке ненульове ціле число 1
в канонічне булеве справжнє значення.
В цілому, однак, я вважаю, що набагато краще порівняти порівняно, ніж використовувати цю незвичайну ідіому:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
Це корисно, якщо вам потрібно зробити ексклюзив або . Копіювання відповіді Метта Ван Хорна з незначними змінами:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
Я використовував це для того, щоб дві змінні були або нульовими, або обома не нульовими.
raise "Inconsistency" if !!a ^ !!b
Це "подвійно-негативно", але практика відлякує. Якщо ви використовуєте rubocop , ви побачите, що він скаржиться на такий код із Style/DoubleNegation
порушенням.
В обґрунтування стану:
Оскільки це однозначно і зазвичай є зайвим, цього слід уникати [тоді перефразовуючи:] Змінити
!!something
на!something.nil?
!!false # => false
поки!false.nil? # => true
!(foo.nil? || foo == false)
- більш багатослівний, так, але менш дурний.
Розуміння того, як це працює, може бути корисним, якщо вам потрібно перетворити, скажімо, перерахування в булеве. У мене є код, який робить саме це, використовуючи classy_enum
дорогоцінний камінь:
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.