significado manera igualmente igual forma existe ejemplo cual conector ruby comparison operators equality

ruby - manera - ¿Cuál es la diferencia entre igual, eql ?,=== y==?



igualmente existe (7)

=== # --- caso de igualdad

== # --- igualdad genérica

ambos funcionan de manera similar pero "===" incluso hacen declaraciones de caso

"test" == "test" #=> true "test" === "test" #=> true

aquí la diferencia

String === "test" #=> true String == "test" #=> false

Estoy tratando de entender la diferencia entre estos cuatro métodos. Sé por defecto que == llama al método equal? que devuelve verdadero cuando ambos operandos se refieren exactamente al mismo objeto.

=== por defecto también llama == que llama equal? ... está bien, entonces si estos tres métodos no se anulan, entonces supongo que === , == e equal? hacer exactamente lo mismo?

Ahora viene eql? . ¿Qué hace esto (por defecto)? ¿Hace una llamada al hash / id del operando?

¿Por qué Ruby tiene tantos signos de igualdad? ¿Se supone que difieren en la semántica?


Operadores de igualdad: == y! =

El operador ==, también conocido como igualdad o doble igual, devolverá verdadero si ambos objetos son iguales y falso si no lo son.

"koan" == "koan" # Output: => true

El operador! =, AKA desigualdad o bang-tilde, es el opuesto de ==. Devolverá verdadero si ambos objetos no son iguales y falsos si son iguales.

"koan" != "discursive thought" # Output: => true

Tenga en cuenta que dos matrices con los mismos elementos en un orden diferente no son iguales, las versiones en mayúsculas y minúsculas de la misma letra no son iguales y así sucesivamente.

Al comparar números de diferentes tipos (por ejemplo, entero y flotante), si su valor numérico es el mismo, == devolverá verdadero.

2 == 2.0 # Output: => true

¿igual?

A diferencia del operador == que prueba si ambos operandos son iguales, el método igual verifica si los dos operandos se refieren al mismo objeto. Esta es la forma más estricta de igualdad en Ruby.

Ejemplo: a = "zen" b = "zen"

a.object_id # Output: => 20139460 b.object_id # Output :=> 19972120 a.equal? b # Output: => false

En el ejemplo anterior, tenemos dos cadenas con el mismo valor. Sin embargo, son dos objetos distintos, con diferentes ID de objeto. Por lo tanto, el igual? El método devolverá false.

Intentemos nuevamente, solo que esta vez b será una referencia a a. Observe que el ID de objeto es el mismo para ambas variables, ya que apuntan al mismo objeto.

a = "zen" b = a a.object_id # Output: => 18637360 b.object_id # Output: => 18637360 a.equal? b # Output: => true

eql?

En la clase Hash, ¿el eql? Método que se utiliza para probar las claves de igualdad. Se requieren algunos antecedentes para explicar esto. En el contexto general de la computación, una función de hash toma una cadena (o un archivo) de cualquier tamaño y genera una cadena o entero de tamaño fijo llamado hashcode, comúnmente denominado solo hash. Algunos tipos de código de hash comúnmente usados ​​son MD5, SHA-1 y CRC. Se utilizan en algoritmos de cifrado, indexación de bases de datos, verificación de integridad de archivos, etc. Algunos lenguajes de programación, como Ruby, proporcionan un tipo de colección llamada tabla hash. Las tablas hash son colecciones parecidas a diccionarios que almacenan datos en pares, que consisten en claves únicas y sus valores correspondientes. Bajo el capó, esas claves se almacenan como códigos hash. Las tablas hash son comúnmente denominadas simplemente hashes. Observe cómo la palabra hashcan puede referirse a un código hash o a una tabla hash. En el contexto de la programación de Ruby, la palabra hash casi siempre se refiere a la colección similar a un diccionario.

Ruby proporciona un método incorporado llamado hash para generar códigos hash. En el siguiente ejemplo, toma una cadena y devuelve un código hash. Observe cómo las cadenas con el mismo valor siempre tienen el mismo código hash, aunque sean objetos distintos (con diferentes ID de objeto).

"meditation".hash # Output: => 1396080688894079547 "meditation".hash # Output: => 1396080688894079547 "meditation".hash # Output: => 1396080688894079547

El método hash se implementa en el módulo Kernel, incluido en la clase Object, que es la raíz predeterminada de todos los objetos de Ruby. Algunas clases como Symbol y Integer usan la implementación predeterminada, otras como String y Hash proporcionan sus propias implementaciones.

Symbol.instance_method(:hash).owner # Output: => Kernel Integer.instance_method(:hash).owner # Output: => Kernel String.instance_method(:hash).owner # Output: => String Hash.instance_method(:hash).owner # Output: => Hash

En Ruby, cuando almacenamos algo en un hash (colección), el objeto proporcionado como clave (p. Ej., Cadena o símbolo) se convierte y se almacena como un código hash. Más adelante, al recuperar un elemento del hash (colección), proporcionamos un objeto como clave, que se convierte en un código hash y se compara con las claves existentes. Si hay una coincidencia, se devuelve el valor del elemento correspondiente. La comparación se realiza utilizando el eql? Método bajo el capó.

"zen".eql? "zen" # Output: => true # is the same as "zen".hash == "zen".hash # Output: => true

En la mayoría de los casos, el eql? El método se comporta de manera similar al método ==. Sin embargo, hay algunas excepciones. Por ejemplo, eql? no realiza una conversión de tipo implícita al comparar un número entero con un flotador.

2 == 2.0 # Output: => true 2.eql? 2.0 # Output: => false 2.hash == 2.0.hash # Output: => false

Operador de igualdad de casos: ===

Muchas de las clases incorporadas de Ruby, como String, Range y Regexp, proporcionan sus propias implementaciones del operador ===, también conocido como igualdad de casos, triple igual o triple calidad. Debido a que se implementa de manera diferente en cada clase, se comportará de manera diferente según el tipo de objeto al que se llamó. En general, devuelve verdadero si el objeto de la derecha "pertenece a" o "es miembro de" el objeto de la izquierda. Por ejemplo, se puede usar para probar si un objeto es una instancia de una clase (o una de sus subclases).

String === "zen" # Output: => true Range === (1..2) # Output: => true Array === [1,2,3] # Output: => true Integer === 2 # Output: => true

El mismo resultado se puede lograr con otros métodos que probablemente sean los más adecuados para el trabajo. Por lo general, es mejor escribir código que sea fácil de leer al ser lo más explícito posible, sin sacrificar la eficiencia y la concisión.

2.is_a? Integer # Output: => true 2.kind_of? Integer # Output: => true 2.instance_of? Integer # Output: => false

Observe que el último ejemplo devolvió false porque los enteros como 2 son instancias de la clase Fixnum, que es una subclase de la clase Integer. El ===, is_a? y instance_of? los métodos devuelven verdadero si el objeto es una instancia de la clase dada o cualquier subclase. El método instance_of es más estricto y solo devuelve verdadero si el objeto es una instancia de esa clase exacta, no una subclase.

El is_a? y kind_of? los métodos se implementan en el módulo Kernel, que se mezcla con la clase Object. Ambos son alias del mismo método. Vamos a verificar:

Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Output: => true

Rango de Implementación de ===

Cuando se llama al operador === en un objeto de rango, devuelve verdadero si el valor de la derecha se encuentra dentro del rango de la izquierda.

(1..4) === 3 # Output: => true (1..4) === 2.345 # Output: => true (1..4) === 6 # Output: => false ("a".."d") === "c" # Output: => true ("a".."d") === "e" # Output: => false

Recuerde que el operador === invoca el método === del objeto de la izquierda. Entonces (1..4) === 3 es equivalente a (1..4) .== 3. En otras palabras, la clase del operando de la izquierda definirá qué implementación del método === será Llamado, por lo que las posiciones del operando no son intercambiables.

Implementación Regexp de ===

Devuelve verdadero si la cadena de la derecha coincide con la expresión regular de la izquierda. / zen / === "practicar zazen hoy" # Salida: => verdadero # es lo mismo que "practicar zazen hoy" = ~ / zen /

Uso implícito del operador === en el caso / cuando las declaraciones

Este operador también se utiliza bajo el capó en las declaraciones de caso / cuándo. Ese es su uso más común.

minutes = 15 case minutes when 10..20 puts "match" else puts "no match" end # Output: match

En el ejemplo anterior, si Ruby hubiera utilizado implícitamente el operador doble igual (==), el rango 10..20 no se consideraría igual a un número entero como el 15. Coinciden porque el operador triple igual (===) es Usado implícitamente en todos los casos / cuando las declaraciones. El código en el ejemplo anterior es equivalente a:

if (10..20) === minutes puts "match" else puts "no match" end

Operadores de coincidencia de patrones: = ~ y! ~

Los operadores = ~ (tilde igual) y! ~ (Bang-tilde) se utilizan para hacer coincidir cadenas y símbolos con patrones de expresiones regulares.

La implementación del método = ~ en las clases Cadena y Símbolo espera una expresión regular (una instancia de la clase Regexp) como argumento.

"practice zazen" =~ /zen/ # Output: => 11 "practice zazen" =~ /discursive thought/ # Output: => nil :zazen =~ /zen/ # Output: => 2 :zazen =~ /discursive thought/ # Output: => nil

La implementación en la clase Regexp espera una cadena o un símbolo como argumento.

/zen/ =~ "practice zazen" # Output: => 11 /zen/ =~ "discursive thought" # Output: => nil

En todas las implementaciones, cuando la cadena o el símbolo coinciden con el patrón Regexp, devuelve un entero que es la posición (índice) de la coincidencia. Si no hay coincidencia, devuelve nula. Recuerde que, en Ruby, cualquier valor entero es "truthy" y nil es "falsy", por lo que el operador = ~ se puede usar en sentencias if y operadores ternarios.

puts "yes" if "zazen" =~ /zen/ # Output: => yes "zazen" =~ /zen/?"yes":"no" # Output: => yes

Los operadores de coincidencia de patrones también son útiles para escribir declaraciones if más cortas. Ejemplo:

if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin" true end Can be rewritten as: if meditation_type =~ /^(zazen|shikantaza|kinhin)$/ true end

El operador! ~ Es el opuesto de = ~, devuelve verdadero cuando no hay coincidencia y falso si hay una coincidencia.

Más información está disponible en este blog .


Escribí una prueba simple para todo lo anterior.

def eq(a, b) puts "#{[a, ''=='', b]} : #{a == b}" puts "#{[a, ''==='', b]} : #{a === b}" puts "#{[a, ''.eql?'', b]} : #{a.eql?(b)}" puts "#{[a, ''.equal?'', b]} : #{a.equal?(b)}" end eq("all", "all") eq(:all, :all) eq(Object.new, Object.new) eq(3, 3) eq(1, 1.0)


Me encanta la respuesta de jtbandes, pero como es bastante larga, agregaré mi propia respuesta compacta:

== , === , eql? , equal?
Son 4 comparadores, es decir. 4 maneras de comparar 2 objetos, en Ruby.
Como en Ruby, todos los comparadores (y la mayoría de los operadores) son en realidad llamadas a métodos, puedes cambiar, sobrescribir y definir la semántica de estos métodos de comparación. Sin embargo, es importante entender, cuando las construcciones de lenguaje internas de Ruby usan qué comparador:

== (comparación de valores)
Ruby usa: == en todas partes para comparar los valores de 2 objetos, ej. Hash-valores:

{a: ''z''} == {a: ''Z''} # => false {a: 1} == {a: 1.0} # => true

=== (comparación de casos)
Ruby usa: === en caso / cuando construye. Los siguientes fragmentos de código son lógicamente idénticos:

case foo when bar; p ''do something'' end if bar === foo p ''do something'' end

eql? (Comparación de hash-key)
Ruby usa: eql? (en combinación con el método hash) para comparar Hash-keys. En la mayoría de las clases: eql? es idéntico a: ==.
Conocimiento sobre: ​​eql? Solo es importante, cuando quieres crear tus propias clases especiales:

class Equ attr_accessor :val alias_method :initialize, :val= def hash() self.val % 2 end def eql?(other) self.hash == other.hash end end h = {Equ.new(3) => 3, Equ.new(8) => 8, Equ.new(15) => 15} #3 entries, but 2 are :eql? h.size # => 2 h[Equ.new(27)] # => 15

Nota: el conjunto de clase Ruby que se usa comúnmente también se basa en la comparación de clave de hash.

equal? (comparación de identidad de objeto)
Rubí utiliza: igual? para comprobar si dos objetos son idénticos. Este método (de la clase BasicObject) no se debe sobrescribir.

obj = obj2 = ''a'' obj.equal? obj2 # => true obj.equal? obj.dup # => false


Me gustaría expandir el operador ===

=== no es un operador de igualdad!

No.

Vamos a transmitir ese punto realmente.

Puede estar familiarizado con === como operador de igualdad en Javascript y PHP, pero este no es un operador de igualdad en Ruby y tiene una semántica fundamentalmente diferente.

Entonces, ¿qué hace === hacer?

=== es el operador de coincidencia de patrones!

  • === coincide con expresiones regulares
  • === comprueba rango de membresía
  • === verifica ser instancia de una clase
  • === llama expresiones lambda
  • === veces se comprueba la igualdad, pero sobre todo no

Entonces, ¿cómo esta locura tiene sentido?

  • Enumerable#grep usa === internamente
  • case when declaraciones usan === internamente
  • Dato curioso, los usos de rescue === internamente

Es por eso que puede usar expresiones regulares y clases y rangos, e incluso expresiones lambda en un case when declaración.

Algunos ejemplos

case value when /regexp/ # value matches this regexp when 4..10 # value is in range when MyClass # value is an instance of class when ->(value) { ... } # lambda expression returns true when a, b, c, d # value matches one of a through d with `===` when *array # value matches an element in array with `===` when x # values is equal to x unless x is one of the above end

Todos estos ejemplos funcionan con el pattern === value también, así como con el método grep .

arr = [''the'', ''quick'', ''brown'', ''fox'', 1, 1, 2, 3, 5, 8, 13] arr.grep(/[qx]/) # => ["quick", "fox"] arr.grep(4..10) # => [5, 8] arr.grep(String) # => ["the", "quick", "brown", "fox"] arr.grep(1) # => [1, 1]


Ruby expone varios métodos diferentes para manejar la igualdad:

a.equal? ​​(b) # identidad de objeto - a y b se refieren al mismo objeto

a.eql? (b) # equivalencia de objetos - a y b tienen el mismo valor

a == b # equivalencia de objetos - a y b tienen el mismo valor con la conversión de tipo.

Continúe leyendo haciendo clic en el enlace de abajo, me dio una comprensión clara y resumida.

https://www.relishapp.com/rspec/rspec-expectations/v/2-0/docs/matchers/equality-matchers

Espero que ayude a los demás.


Voy a citar mucho la documentación del Objeto aquí, porque creo que tiene algunas explicaciones geniales. Lo aliento a que lo lea, y también la documentación de estos métodos, ya que están anulados en otras clases, como String .

Nota al margen: si quieres probar esto por ti mismo en diferentes objetos, usa algo como esto:

class Object def all_equals(o) ops = [:==, :===, :eql?, :equal?] Hash[ops.map(&:to_s).zip(ops.map {|s| send(s, o) })] end end "a".all_equals "a" # => {"=="=>true, "==="=>true, "eql?"=>true, "equal?"=>false}

== - "igualdad" genérica

En el nivel de objeto, == devuelve verdadero solo si obj y other son el mismo objeto. Normalmente, este método se reemplaza en las clases descendientes para proporcionar un significado específico de la clase.

Esta es la comparación más común y, por lo tanto, el lugar más fundamental donde usted (como autor de una clase) puede decidir si dos objetos son "iguales" o no.

=== - igualdad de casos

Para la clase Objeto, efectivamente es lo mismo que llamar #== , pero generalmente los descendientes lo anulan para proporcionar una semántica significativa en las declaraciones de casos.

Esto es increíblemente útil. Ejemplos de cosas que tienen implementaciones interesantes === :

  • Distancia
  • Regex
  • Proc (en Ruby 1.9)

Así que puedes hacer cosas como:

case some_object when /a regex/ # The regex matches when 2..4 # some_object is in the range 2..4 when lambda {|x| some_crazy_custom_predicate } # the lambda returned true end

Vea mi respuesta aquí para ver un buen ejemplo de cómo case + Regex puede hacer que el código sea mucho más limpio. Y, por supuesto, al proporcionar su propia implementación === , puede obtener semánticas de case personalizados.

eql? - Hash Equidad

El eql? El método devuelve true si obj y other refieren a la misma clave hash. Esto es utilizado por Hash para probar la igualdad de los miembros. Para objetos de la clase Object , eql? es sinónimo de == . Las subclases normalmente continúan esta tradición aliasing eql? a su método == anulado, pero hay excepciones. Numeric tipos Numeric , por ejemplo, realizan conversión de tipo en == , pero no en eql? , asi que:

1 == 1.0 #=> true 1.eql? 1.0 #=> false

Entonces, puede anular esto para sus propios usos, o puede anular == y usar alias :eql? :== alias :eql? :== entonces los dos métodos se comportan de la misma manera.

equal? - comparación de identidad

A diferencia de == , el equal? el método nunca debe ser invalidado por las subclases: se utiliza para determinar la identidad del objeto (es decir, a.equal?(b) iff a es el mismo objeto que b ).

Esto es efectivamente la comparación de punteros.