Risposte:
Non non. È usato per convertire un valore in un valore booleano:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
Di solito non è necessario usarlo, dato che gli unici falsi valori di Ruby sono nil
e false
, quindi di solito è meglio lasciar stare quella convenzione.
Pensalo come
!(!some_val)
Una cosa utilizzata per legittimamente è impedire la restituzione di un enorme blocco di dati. Ad esempio, probabilmente non vuoi restituire 3 MB di dati immagine nel tuo has_image?
metodo, oppure potresti non voler restituire l'intero oggetto utente nel logged_in?
metodo. L'utilizzo !!
converte questi oggetti in un semplice true
/ false
.
.nil?
invece di usare !!
? C'è una differenza?
!!true #=> true
etrue.nil? #=> false
!
significa negare lo stato booleano, due !
s non è niente di speciale, a parte una doppia negazione.
!true == false
# => true
È comunemente usato per forzare un metodo per restituire un valore booleano. Rileverà qualsiasi tipo di verità, come stringa, numeri interi e cosa no, e lo trasformerà in un valore booleano.
!"wtf"
# => false
!!"wtf"
# => true
Un caso d'uso più reale:
def title
"I return a string."
end
def title_exists?
!!title
end
Ciò è utile quando si desidera assicurarsi che venga restituito un valore booleano. IMHO è in qualche modo inutile, visto che entrambi if 'some string'
ed if true
è esattamente lo stesso flusso, ma alcune persone trovano utile restituire esplicitamente un booleano.
title
, può anche fare la cosa più vicina ad esso ... Suppongo
Nota che questo linguaggio esiste anche in altri linguaggi di programmazione. C non aveva un bool
tipo intrinseco , quindi tutti i booleani venivano digitati come int
invece, con valori canonici di 0
o 1
. Fa questo esempio (parentesi aggiunte per maggiore chiarezza):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
La sintassi "non-no" converte qualsiasi numero intero diverso da zero in 1
, il valore vero booleano canonico.
In generale, però, trovo molto meglio fare un confronto ragionevole piuttosto che usare questo linguaggio insolito:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
È utile se devi fare un esclusivo o . Copia dalla risposta di Matt Van Horn con lievi modifiche:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
L'ho usato per assicurarmi che due variabili fossero entrambe nulle o entrambe non nulle.
raise "Inconsistency" if !!a ^ !!b
È "doppio negativo", ma la pratica viene scoraggiata. Se stai usando rubocop , lo vedrai lamentarti di tale codice con aStyle/DoubleNegation
violazione.
La logica afferma:
Poiché questo è sia criptico che di solito ridondante, dovrebbe essere evitato [quindi parafrasando:] Passa
!!something
a!something.nil?
!!false # => false
mentre!false.nil? # => true
!(foo.nil? || foo == false)
- più prolisso, sì, ma meno criptico.
Comprendere come funziona può essere utile se è necessario convertire, per esempio, un elenco in un valore booleano. Ho un codice che fa esattamente questo, usando la classy_enum
gemma:
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
Quindi nel codice di servizio ho, ad esempio:
raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states.
In effetti l'operatore bangbang è diventato ciò che altrimenti avrei potuto scrivere come un metodo chiamato to_bool.