2009-02-07 25 views

Respuesta

145

No, no. Se utiliza para convertir un valor a un valor lógico:

!!nil #=> false 
!!"abc" #=> true 
!!false #=> false 

Por lo general, no es necesario el uso de embargo ya que los únicos valores falsos a Ruby son nil y false, por lo que por lo general es mejor dejar que el soporte de convenciones.

pensar en él como

!(!some_val) 

Una cosa que es lo utiliza legítimamente está impidiendo que una gran parte de los datos de ser devuelto. Por ejemplo, probablemente no desee devolver 3MB de datos de imagen en su método has_image?, o puede que no desee devolver el objeto de usuario completo en el método logged_in?. El uso de !! convierte estos objetos en un simple true/false.

+3

Así que es una doble negación? – Ross

+6

No es una mala práctica usar esto. Double bang se usa a menudo en predicados (métodos que terminan en?) Para devolver un valor explícitamente booleano. – Swanand

+6

Alex, que en realidad no tiene que preocuparse acerca de regresar objetos grandes, como Ruby devolver una referencia, no una copia del objeto. – DSimon

28

Devuelve true si el objeto de la derecha no es nil y no false, false si es nil o false

def logged_in? 
    [email protected]_user 
end 
+1

¿Era obvio que venía de Restful_Auth? : D – Cameron

+0

No solo si es nulo. – womble

6

Tenga en cuenta que existe este idioma en otros lenguajes de programación también. C no tenía un tipo intrínseco bool, por lo que todos los booleanos se escribieron como int, con valores canónicos de 0 o 1. Toma este ejemplo (paréntesis añadido para mayor claridad):

!(1234) == 0 
!(0) == 1 
!(!(1234)) == 1 

El "no-no" sintaxis convierte cualquier número entero no nulo a 1, el verdadero valor booleano canónica.

En general, sin embargo, creo que es mucho mejor para poner en una comparación razonable de utilizar este idioma raro:

int x = 1234; 
if (!!x); // wtf mate 
if (x != 0); // obvious 
+0

O simplemente si (x). !! es útil cuando necesita obtener 0/1. Usted puede o no considerar (x)? 1: 0 más claro. – derobert

14

! medios niegan estado booleano, dos ! s es nada especial, aparte de una doble negación

!true == false 
# => true 

Se utiliza comúnmente para forzar un método para devolver un valor booleano. Detectará cualquier tipo de veracidad, como cadena, enteros y demás, y lo convertirá en un booleano.

!"wtf" 
# => false 

!!"wtf" 
# => true 

Un caso de uso más real:

def title 
    "I return a string." 
end 

def title_exists? 
    !!title 
end 

Esto es útil cuando se quiere asegurarse de que se devuelve un valor lógico. En mi humilde opinión, no tiene sentido, ya que tanto if 'some string' como if true es exactamente el mismo flujo, pero a algunas personas les resulta útil devolver explícitamente un booleano.

+0

me parece como sólo una forma más rápida que usando una sentencia if o un operador ternario. Como no puede devolver el 'título', también puede hacer lo más parecido ... Supongo –

3

Es útil si necesita hacer un exclusive or.La copia de la respuesta de Matt Van Horn con ligeras modificaciones:

1^true 
TypeError: can't convert true into Integer 

!!1^!!true 
=> false 

que lo usaron para asegurar dos variables fueron ya sea tanto nula, o ambos, no nulo.

raise "Inconsistency" if !!a^!!b 
0

Entender cómo funciona puede ser útil si necesita convertir, por ejemplo, una enumeración en un booleano. Tengo el código que hace exactamente eso, utilizando el classy_enum joya:

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 

Luego, en el código de servicio que tienen, por ejemplo:

raise Application::Error unless !!object.link_status # => raises exception for "No" and "Denied" states. 

Efectivamente el operador bangbang se ha convertido en lo que de otro modo podría haber escrito como un método llamado to_bool.

3

que es "doble negación", pero se está desalentado la práctica. Si está utilizando rubocop, verá que se quejan de dicho código con una violación Style/DoubleNegation.

Los rationale estados:

Como se trata tanto críptico y generalmente redundante, debe evitarse [entonces parafraseando:] Cambiar !!something a !something.nil?

+0

Pero ... ' '' !! false # => false''' while '' ' ! false.nil? # => verdadero''' – Doug