=== vs == en Ruby
En Ruby, ¿cuál es la diferencia entre == y ===? El RDoc dice
Igualdad de casos: para la clase Objeto, en realidad es lo mismo que llamar a #==, pero normalmente los descendientes lo anulan para proporcionar una semántica significativa en las declaraciones de caso.
Es #==
lo mismo que ==
? ¿Y podría darnos un ejemplo de cuándo y cómo se utiliza esto en declaraciones de caso?
Los dos realmente no tienen nada que ver el uno con el otro. En particular, #==
es el operador de igualdad y #===
no tiene absolutamente nada que ver con la igualdad. Personalmente, me parece bastante desafortunado que #===
se parezca tanto a #==
, use el signo igual y a menudo se le llame operador de igualdad de casos , operador triple igual o operador tres iguales cuando en realidad no tiene nada que ver con la igualdad.
Llamo #===
al operador de subsunción de casos (es lo mejor que se me ocurrió, estoy abierto a sugerencias, especialmente de hablantes nativos de inglés).
La mejor manera de describirlo a === b
es "si tengo un cajón con la etiqueta a
, ¿tiene sentido colocarlo b
allí?"
Entonces, por ejemplo, Module#===
prueba si b.is_a?(a)
. Si es así Integer === 2
, ¿tiene sentido ponerlo 2
en una caja etiquetada Integer
? Sí, lo hace. Qué pasa Integer === 'hello'
? Obviamente no.
Otro ejemplo es Regexp#===
. Prueba una coincidencia. ¿Tiene sentido ponerlo 'hello'
en una caja etiquetada /el+/
? Sí, lo hace.
Para colecciones como rangos, Range#===
se define como una prueba de membresía: tiene sentido colocar un elemento en un cuadro etiquetado con una colección si ese elemento está en la colección.
Entonces, eso es lo que #===
hace: prueba si el argumento puede incluirse en el receptor.
¿Qué tiene eso que ver con case
las expresiones? Simple:
case foo
when bar
baz
end
es lo mismo que
if bar === foo
baz
end
Sí, #==
los documentos significan "el método de instancia ==
del objeto actual".
===
se utiliza en declaraciones de caso como tales:
case obj
when x
foo
when y
bar
end
Es lo mismo que
if x === obj
foo
elsif y === obj
bar
end
Algunas clases que se definen ===
son Range (actuar como include?
), Clase (actuar como obj.is_a?(klass)
) y Regexp
(actuar como =~
excepto devolver un valor booleano). Algunas clases que no se definen ===
son las clases numéricas y String.
Entonces
case x
when 0
puts "Lots"
when Numeric
puts(100.0 / x)
when /^\d+$/
puts(100.0 / x.to_f)
default
raise ArgumentError, "x is not a number or numeric string"
end
es lo mismo que
if 0 == x
puts "Lots"
elsif x.is_a? Numeric
puts(100.0 / x)
elsif x =~ /^\d+$/
puts(100.0 / x.to_f)
else
raise ArgumentError, "x is not a number or numeric string"
end