Pregunta if (! x) vs if (x == falso) en ruby


No entiendo el siguiente código:

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 una base C, al menos), if (! Cond) y if (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).


11
2018-06-21 05:38


origen


Respuestas:


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

Escritura foo == bar siempre llamará al == método en foo con bar como un argumento Por defecto, nil, false, true y todas las otras inmediatas como símbolos, etc., son solo iguales a ellas mismas. 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 !, asi que unless foo no es necesariamente lo mismo que if !foo o lo contrario de if foo:

def true.!
  true
end

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

No es que nadie recomiende hacer algo como esto ...


31
2018-06-21 05:52



nil no es igual a falso en comparación sobre == porque su contenido semántico es diferente (nil no hay información, falso es un valor booleano). Sin embargo, si intentas 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.

Entonces solo puedes decir que 'nil no es verdad' y 'nil is nil'. Esto es tan lejos como Ruby va en su camino.


2
2018-06-21 05:41



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.


0
2018-06-21 05:42