2010-10-22 7 views
74

Duplicar posibles:
What does !! mean in ruby?Ruby, !! operador (a/k/a la doble explosión)

Hola,

Soy nuevo en Ruby y no puedo encontrar en cualquier lugar descripción de lo que "!!" medio.

He aquí un ejemplo:

def signed_in? 
    !!current_user 
end 

Si se trata de una doble negación, por qué no decirlo:

def signed_in? 
    current_user 
end 

por favor ayuda.

+0

¿Hizo una ojeada a las preguntas, que le fueron dadas después de que escribió el título de su pregunta? – Nakilon

+4

Sí, no había nada allí. De hecho, encontré una pregunta similar que me explicaba la segunda pregunta, pero tuve que buscar por "doble explosión", lo cual no es tan obvio como podría pensar. – Vitaly

+3

Sí, el algoritmo de preguntas similares se engaña fácilmente cuando partes importantes del título son caracteres de puntuación. – pkaeding

Respuesta

98

En la mayoría de los lenguajes de programación, incluido Ruby, ! devolverá el valor opuesto al booleano del operando. Entonces, cuando encadena dos signos de exclamación, convierte el valor a booleano.

121

En Ruby (y en muchos otros idiomas) hay muchos valores que se evalúan como true en un contexto booleano, y algunos que se evaluarán como falsos. En Ruby, the only two things that evaluate to false are false (itself) and nil.

Si niega algo, eso fuerza un contexto booleano. Por supuesto, también lo niega. Si lo niega dos veces, fuerza el contexto booleano, pero devuelve el valor booleano adecuado.

Por ejemplo:

"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) 

En su ejemplo, el método signed_in? debería devolver un valor booleano (como se indica por convención por el carácter ?). La lógica interna que utiliza para decidir este valor es verificando si la variable current_user está configurada. Si está configurado, se evaluará a true en un contexto booleano. Si no, se evaluará como falso. La doble negación obliga al valor de retorno a ser booleano.

+0

así que! "" Es forzar a ** verdadero ** y !! "" a ** falso ** o la cadena vacía también es verdadera? – berto77

+1

'!" "' Es 'falso', porque los únicos valores de falso-y son' falso' y 'nil'. Todo lo demás es verdad-y: http://phrogz.net/ProgrammingRuby/language.html#truthvalues ​​He editado mi respuesta para que quede más claro. – pkaeding

+2

Esta es la mejor respuesta porque explica POR QUÉ. Parece que el mismo tipo de hack que se ve en Java a veces para convertir un int en un String añadiéndole un "" (que por cierto NO estoy defendiendo, creo que esto es una mala práctica en Java). Dado que esta es una mala práctica en Java, no entiendo por qué idiomas como Ruby lo están adoptando. ¿Todo para usar la menor cantidad de caracteres posible? –

27

!! es solo ! (el operador de negación booleana) escrito dos veces. Niega el argumento, luego niega la negación. Es útil porque puede usarlo para obtener un booleano de cualquier valor. El primer ! convertirá el argumento a booleano, p. true si es nil o false, y false en caso contrario. El segundo negará eso nuevamente para que obtenga el valor booleano del argumento, false para nil o false, true para casi todo lo demás.

En Ruby puede usar cualquier valor en una declaración if, p. Ej. if current_user se ejecutará si el usuario actual no es nil. La mayoría de las veces esto es genial porque nos ahorra escribir pruebas explícitas (como if !current_user.nil?, que son al menos seis caracteres más). Pero a veces puede ser realmente confuso si devuelve un objeto cuando el método implica que devuelve un booleano. Los métodos cuyo nombre finaliza con ? deben devolver valores truey o falsy, es decir, devuelven algo que se evaluará a true o false. Sin embargo, puede ser realmente complicado si signed_in? devolvió un objeto de usuario.Por ejemplo, si intenta depurar por qué algún código que usa signed_in? no funciona, es probable que se confunda mucho cuando un objeto de usuario aparece donde esperaba true o false. En esa situación, es útil agregar !! antes del return, ya que eso garantiza que el valor de falsedad o falsedad se devolverá como true o false.

3

Como ha comprendido correctamente, es un uso doblemente negativo del operador !. Dicho esto, si bien puede ser una forma abreviada de comprobar si una variable puede ser nula o no, IMO que es demasiado conciso. Eche un vistazo a this y this publicación. Tenga en cuenta que en Ruby, probar algo a cero se evaluará como falso.

Cuestiones relacionadas