Respuestas:
No no Se utiliza para convertir un valor a un valor booleano:
!!nil #=> false
!!"abc" #=> true
!!false #=> false
Sin embargo, generalmente no es necesario usarlo, ya que los únicos valores falsos para Ruby son nil
y false
, por lo que generalmente es mejor dejar que esa convención permanezca.
Piensa en ello como
!(!some_val)
Una cosa para la que se usa legítimamente es evitar que se devuelva una gran cantidad de datos. Por ejemplo, probablemente no desee devolver 3 MB de datos de imagen en su has_image?
método, o tal vez no desee devolver todo su objeto de usuario en el logged_in?
método. El uso !!
convierte estos objetos a un simple true
/ false
.
.nil?
lugar de usar !!
? ¿Hay una diferencia?
!!true #=> true
ytrue.nil? #=> false
!
significa negar el estado booleano, dos !
s no es nada especial, aparte de una doble negación.
!true == false
# => true
Se usa comúnmente para forzar a un método a devolver un valor booleano. Detectará cualquier tipo de veracidad, como cadenas, 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 desea asegurarse de que se devuelve un valor booleano. En mi humilde opinión es una especie de sentido, sin embargo, al ver que tanto if 'some string'
y if true
es el mismo caudal exacto, pero algunas personas les resulta útil para volver explícitamente un valor lógico.
title
, también puedes hacer lo más parecido a eso ... supongo
Tenga en cuenta que este idioma también existe en otros lenguajes de programación. C no tenía un bool
tipo intrínseco , por lo que todos los booleanos se escribieron como en su int
lugar, con valores canónicos de 0
o 1
. Toma este ejemplo (paréntesis agregados para mayor claridad):
!(1234) == 0
!(0) == 1
!(!(1234)) == 1
La sintaxis "no-no" convierte cualquier número entero distinto de cero en 1
el valor verdadero booleano canónico.
En general, sin embargo, me parece mucho mejor hacer una comparación razonable que usar este idioma poco común:
int x = 1234;
if (!!x); // wtf mate
if (x != 0); // obvious
Es útil si necesita hacer una exclusiva o . Copiando la respuesta de Matt Van Horn con ligeras modificaciones:
1 ^ true
TypeError: can't convert true into Integer
!!1 ^ !!true
=> false
Lo usé para asegurarme de que dos variables fueran nulas o ambas no nulas.
raise "Inconsistency" if !!a ^ !!b
Es "doble negativo", pero se desalienta la práctica. Si está usando rubocop , verá que se queja en dicho código con unStyle/DoubleNegation
violación.
La justificación dice:
Como esto es críptico y generalmente redundante, se debe evitar [parafraseando:] Cambiar
!!something
a!something.nil?
!!false # => false
mientras!false.nil? # => true
!(foo.nil? || foo == false)
: más detallado, sí, pero menos críptico.
Comprender cómo funciona puede ser útil si necesita convertir, por ejemplo, una enumeración en un booleano. Tengo un código que hace exactamente eso, usando la classy_enum
gema:
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 tengo, 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.