2010-10-22 10 views
74

Eventuali duplicati:
What does !! mean in ruby?Ruby, !! operatore (a/k/al doppio-bang)

Ciao,

Sono nuovo di Ruby e non riesco a trovare da nessuna parte descrizione di cosa "!!" si intende.

Ecco un esempio:

def signed_in? 
    !!current_user 
end 

Se questo è un doppio negativo, perché non dire:

def signed_in? 
    current_user 
end 

prega di aiuto.

+0

Hai dato un'occhiata alle domande che ti sono state fornite dopo aver digitato il titolo della domanda? – Nakilon

+4

Sì, non c'era niente lì. In realtà ho trovato una domanda simile spiegandomi la seconda domanda, ma ho dovuto cercare "double bang" che non è così ovvio come si potrebbe pensare. – Vitaly

+3

Sì, l'algoritmo di domande simili viene ingannato facilmente quando parti importanti del titolo sono caratteri di punteggiatura. – pkaeding

risposta

98

Nella maggior parte dei linguaggi di programmazione, incluso Ruby, ! restituirà l'opposto del valore booleano dell'operando. Pertanto, quando si uniscono due punti esclamativi, converte il valore in un valore booleano.

121

In Ruby (e in molti altri linguaggi) ci sono molti valori che valutano in true in un contesto booleano e una manciata che valuterà in falso. In Ruby, the only two things that evaluate to false are false (itself) and nil.

Se si nega qualcosa, questo impone un contesto booleano. Certo, lo nega anche. Se lo si nega, esso impone il contesto booleano, ma restituisce il valore booleano corretto.

Ad esempio:

"hello" #-> this is a string; it is not in a boolean context 
!"hello" #-> this is a string that is forced into a boolean 
      # context (true), and then negated (false) 
!!"hello" #-> this is a string that is forced into a boolean 
      # context (true), and then negated (false), and then 
      # negated again (true) 
!!nil  #-> this is a false-y value that is forced into a boolean 
      # context (false), and then negated (true), and then 
      # negated again (false) 

Nel tuo esempio, il metodo signed_in? dovrebbe restituire un valore booleano (come indicato dalla convenzione dal carattere ?). La logica interna che utilizza per decidere questo valore è verificando se la variabile current_user è impostata. Se è impostato, verrà valutato su true in un contesto booleano. In caso contrario, valuterà come falso. La doppia negazione impone che il valore di ritorno sia un valore booleano.

+0

così! "" È forzato a ** true ** e !! "" a ** falso ** oppure la stringa vuota è vera? – berto77

+1

'!" "' È 'false', perché i soli valori di falsi y sono' false' e ​​'nil'. Tutto il resto è verità-y: http://phrogz.net/ProgrammingRuby/language.html#truthvalues ​​Ho modificato la mia risposta per renderlo più chiaro. – pkaeding

+2

Questa è la risposta migliore perché spiega PERCHÉ. Sembra che lo stesso tipo di hack che si vede in Java a volte converta un int in una String aggiungendo un "" ad esso (che, per il modo in cui NON sto sostenendo, credo che questa sia una cattiva pratica in Java). Dato che questa è una cattiva pratica in Java, non capisco perché lingue come Ruby la stiano abbracciando. Tutto per utilizzare il minor numero di caratteri possibile? –

27

!! è solo ! (l'operatore booleano di negazione) scritto due volte. Negherà l'argomento, quindi annullerà la negazione. È utile perché puoi usarlo per ottenere un valore booleano da qualsiasi valore. Il primo ! convertirà l'argomento in un valore booleano, ad es. true se è nil o false e false in caso contrario. Il secondo lo negherà di nuovo in modo da ottenere il valore booleano dell'argomento, false per nil o false, true per quasi tutto il resto.

In Ruby è possibile utilizzare qualsiasi valore in un'istruzione if, ad es. if current_user verrà eseguito se l'utente corrente non è nil. Il più delle volte questo è fantastico perché ci risparmia digitando test espliciti (come if !current_user.nil?, che è di almeno sei caratteri più lunghi). Ma a volte potrebbe essere davvero confuso se si restituisce un oggetto quando il metodo implica che restituisce un valore booleano. I metodi il cui nome termina con ? dovrebbe restituire valori veri o falsi, cioè restituiscono qualcosa che valuterà in true o false. Tuttavia, può diventare davvero complicato se signed_in? restituisce un oggetto utente.Ad esempio, se stai cercando di eseguire il debug perché un codice che utilizza signed_in? non funziona, probabilmente si confonderà molto quando un oggetto utente si presenterà dove ti aspettavi true o false. In tale situazione è utile aggiungere !! prima dello return poiché è garantito che il valore di verità o di falsità verrà restituito come true o false.

3

Come avete giustamente capito è un uso doppio-negativo dell'operatore !. Detto questo, mentre può essere un modo abbreviato per verificare se una variabile può essere nullo o no, IMO è troppo conciso. Dai un'occhiata al this e al this post. Nota che in Ruby, testare qualcosa a zero valuterà come falso.