2010-06-21 9 views
11

No entiendo el siguiente código (x!):si vs si (x == false) en rubí

ruby-1.9.1-p378 > puts "nil is false" unless nil 
nil is false 
=> nil 
ruby-1.9.1-p378 > puts "nil isn't false" unless nil == false 
nil isn't false 
=> nil 

En la mayoría de los idiomas (de un C-base, por lo menos), si (! cond) y si (cond == false) evalúan lo mismo. ¿Qué está pasando aquí para hacer que no sea el caso?

(me gustaría los detalles de por qué, entiendo que así es como es.)

Respuesta

31

Ruby considera que false y nil son los únicos dos valores "falsy", mientras que todo lo demás es "sincero". Esto es por definición y no se puede modificar (al menos en MRI). Esta definición se utiliza para todos los operadores incorporadas como if, unless, while, until, cond ? if_truthy : if_falsey, ||, &&, ...

Escribir foo == bar siempre llamará al método == en foo con bar como argumento. Por defecto, nil, false, true y todas las demás inmediatas como símbolos, etc., son solo iguales a ellas. Esto podría ser cambiado, sin embargo:

def nil.==(bar) 
    super || bar == false 
end 
puts "nil == false" if nil == false # => "nil == false" 

En Ruby 1.9, también puede redefinir el operador !, por lo unless foo no es necesariamente el mismo que if !foo o al contrario de if foo:

def true.! 
    true 
end 

puts "True?" if true # => "True?" 
puts "or not?" if !true # => "or not?" 

No es que cualquiera recomendaría hacer algo como esto ...

+0

nil no es * realmente falso *, es solo * falsey *. Explicación perfecta +1. Y sí, por favor no anule == o! o lo que sea si no tienes una muy buena razón. – MatrixFrog

+0

+1 para una buena respuesta. Lo mismo es cierto en PHP, que tuvo que inventar el operador '===' (sí, eso es * tres * '=') – Mawg

+0

Muchas gracias por la explicación. –

2

nil no es igual a falsa por comparación a lo largo == porque su contenido semántico es diferente (nil se dispone de información, falso es un valor booleano). Sin embargo, si intenta evaluar nil en un contexto booleano, se considerará False, principalmente por conveniencia y compatibilidad idiomática con otros idiomas.

nil == a <=> nil != a <=> false va a ser el caso para prácticamente cualquier valor de a excepto para nada.

Así que solo se puede decir que 'nil no es verdad' y 'nil is nil'. Esto es tan lejos como Ruby va en su camino.

0

En algunos idiomas, solo puede usar booleanos en sentencias "if". Tratar de verificar si una cadena o un número es verdadero o falso es simplemente tonto y sin sentido, por lo que el lenguaje no te permitirá hacerlo.

En Ruby, sin embargo, todo puede considerarse booleano, aunque en realidad no lo es. De hecho, todo en Ruby es efectivamente cierto, excepto nulo y falso (IIRC). Eso no significa que nil sea en realidad IGUAL a falso, del mismo modo que no significa que el número entero 45 es en realidad igual a verdadero. Son cosas diferentes, separadas. Pero si va a tratar nulo como un booleano (es decir, usarlo en un si o menos), entonces es como si fuera falso.

Cuestiones relacionadas