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 nile 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 #=> trueetrue.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 booltipo intrinseco , quindi tutti i booleani venivano digitati come intinvece, con valori canonici di 0o 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
!!somethinga!something.nil?
!!false # => falsementre!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_enumgemma:
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.