Operadores de igualdade: == e! =
O operador ==, também conhecido como igualdade ou duplo igual, retornará true se os dois objetos forem iguais e false se não forem.
"koan" == "koan" # Output: => true
O operador! =, Também conhecido como desigualdade, é o oposto de ==. Retornará true se os dois objetos não forem iguais e false se forem iguais.
"koan" != "discursive thought" # Output: => true
Observe que duas matrizes com os mesmos elementos em uma ordem diferente não são iguais, versões em maiúsculas e minúsculas da mesma letra não são iguais e assim por diante.
Ao comparar números de tipos diferentes (por exemplo, número inteiro e número flutuante), se o valor numérico for o mesmo, == retornará verdadeiro.
2 == 2.0 # Output: => true
igual?
Diferente do operador == que testa se os dois operandos são iguais, o método equal verifica se os dois operandos se referem ao mesmo objeto. Esta é a forma mais estrita de igualdade em Ruby.
Exemplo: a = "zen" b = "zen"
a.object_id # Output: => 20139460
b.object_id # Output :=> 19972120
a.equal? b # Output: => false
No exemplo acima, temos duas cadeias com o mesmo valor. No entanto, eles são dois objetos distintos, com diferentes IDs de objeto. Portanto, o igual? O método retornará false.
Vamos tentar novamente, só que desta vez b será uma referência a. Observe que o ID do objeto é o mesmo para as duas variáveis, pois elas apontam para o mesmo objeto.
a = "zen"
b = a
a.object_id # Output: => 18637360
b.object_id # Output: => 18637360
a.equal? b # Output: => true
eql?
Na classe Hash, o eql? método é usado para testar chaves para igualdade. Alguns antecedentes são necessários para explicar isso. No contexto geral da computação, uma função hash pega uma string (ou um arquivo) de qualquer tamanho e gera uma string ou um número inteiro de tamanho fixo chamado hashcode, geralmente chamado apenas de hash. Alguns tipos de código de hash comumente usados são MD5, SHA-1 e CRC. Eles são usados em algoritmos de criptografia, indexação de banco de dados, verificação de integridade de arquivos etc. Algumas linguagens de programação, como Ruby, fornecem um tipo de coleção chamado tabela de hash. As tabelas de hash são coleções semelhantes a dicionários que armazenam dados em pares, consistindo em chaves exclusivas e seus valores correspondentes. Sob o capô, essas chaves são armazenadas como códigos de hash. As tabelas de hash são comumente referidas como apenas hashes. Observe como a palavra hashcan se refere a um hashcode ou a uma tabela de hash.
O Ruby fornece um método interno chamado hash para gerar códigos de hash. No exemplo abaixo, ele pega uma string e retorna um código hash. Observe como seqüências de caracteres com o mesmo valor sempre têm o mesmo código de hash, mesmo que sejam objetos distintos (com IDs de objeto diferentes).
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
"meditation".hash # Output: => 1396080688894079547
O método hash é implementado no módulo Kernel, incluído na classe Object, que é a raiz padrão de todos os objetos Ruby. Algumas classes, como Symbol e Inteiro, usam a implementação padrão, outras como String e Hash fornecem suas próprias implementações.
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
No Ruby, quando armazenamos algo em um hash (coleção), o objeto fornecido como uma chave (por exemplo, string ou símbolo) é convertido e armazenado como um código de hash. Mais tarde, ao recuperar um elemento do hash (coleção), fornecemos um objeto como uma chave, que é convertida em um código de hash e comparada às chaves existentes. Se houver uma correspondência, o valor do item correspondente será retornado. A comparação é feita usando o eql? método sob o capô.
"zen".eql? "zen" # Output: => true
# is the same as
"zen".hash == "zen".hash # Output: => true
Na maioria dos casos, o eql? O método se comporta de maneira semelhante ao método ==. No entanto, existem algumas exceções. Por exemplo, eql? não realiza conversão implícita de tipo ao comparar um número inteiro a um número flutuante.
2 == 2.0 # Output: => true
2.eql? 2.0 # Output: => false
2.hash == 2.0.hash # Output: => false
Operador de igualdade de caso: ===
Muitas das classes internas do Ruby, como String, Range e Regexp, fornecem suas próprias implementações do operador ===, também conhecido como igualdade entre maiúsculas e minúsculas, iguais a triplos ou três iguais. Como é implementado de maneira diferente em cada classe, ele se comportará de maneira diferente, dependendo do tipo de objeto em que foi chamado. Geralmente, ele retornará true se o objeto à direita "pertencer a" ou "for um membro" do objeto à esquerda. Por exemplo, ele pode ser usado para testar se um objeto é uma instância de uma classe (ou uma de suas subclasses).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
O mesmo resultado pode ser alcançado com outros métodos que provavelmente são mais adequados para o trabalho. Geralmente, é melhor escrever um código que seja fácil de ler, sendo o mais explícito possível, sem sacrificar a eficiência e a concisão.
2.is_a? Integer # Output: => true
2.kind_of? Integer # Output: => true
2.instance_of? Integer # Output: => false
Observe que o último exemplo retornou false porque números inteiros como 2 são instâncias da classe Fixnum, que é uma subclasse da classe Integer. O ===, is_a? e instance_of? Os métodos retornam true se o objeto for uma instância da classe especificada ou de qualquer subclasse. O método instance_of é mais rígido e retornará true se o objeto for uma instância dessa classe exata, não uma subclasse.
O is_a? e tipo_de? métodos são implementados no módulo Kernel, que é misturado pela classe Object. Ambos são aliases para o mesmo método. Vamos verificar:
Kernel.instance_method (: kind_of?) == Kernel.instance_method (: is_a?) # Saída: => true
Implementação de intervalo de ===
Quando o operador === é chamado em um objeto de intervalo, ele retorna true se o valor à direita estiver dentro do intervalo à esquerda.
(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
Lembre-se de que o operador === chama o método === do objeto à esquerda. Então (1..4) === 3 é equivalente a (1..4). === 3. Em outras palavras, a classe do operando esquerdo definirá qual implementação do método === será chamado, para que as posições do operando não sejam intercambiáveis.
Implementação Regexp de ===
Retorna true se a sequência à direita corresponder à expressão regular à esquerda. / zen / === "pratique zazen hoje" # Saída: => true # é o mesmo que "pratique zazen hoje" = ~ / zen /
Uso implícito do operador === nas instruções case / when
Este operador também é usado sob o capô nas instruções case / when. Esse é o seu uso mais comum.
minutes = 15
case minutes
when 10..20
puts "match"
else
puts "no match"
end
# Output: match
No exemplo acima, se Ruby tivesse usado implicitamente o operador duplo igual (==), o intervalo 10..20 não seria considerado igual a um número inteiro como 15. Eles correspondem porque o operador triplo igual (===) é implicitamente usado em todas as declarações case / when. O código no exemplo acima é equivalente a:
if (10..20) === minutes
puts "match"
else
puts "no match"
end
Operadores de correspondência de padrões: = ~ e! ~
Os operadores = ~ (equal-til) e! ~ (Bang-til) são usados para comparar cadeias e símbolos com padrões regex.
A implementação do método = ~ nas classes String e Symbol espera uma expressão regular (uma instância da classe Regexp) como argumento.
"practice zazen" =~ /zen/ # Output: => 11
"practice zazen" =~ /discursive thought/ # Output: => nil
:zazen =~ /zen/ # Output: => 2
:zazen =~ /discursive thought/ # Output: => nil
A implementação na classe Regexp espera uma sequência ou um símbolo como argumento.
/zen/ =~ "practice zazen" # Output: => 11
/zen/ =~ "discursive thought" # Output: => nil
Em todas as implementações, quando a sequência ou o símbolo corresponde ao padrão Regexp, ele retorna um número inteiro que é a posição (índice) da correspondência. Se não houver correspondência, ele retornará nulo. Lembre-se de que, em Ruby, qualquer valor inteiro é "verdade" e nulo é "falso"; portanto, o operador = ~ pode ser usado nas instruções if e nos operadores ternários.
puts "yes" if "zazen" =~ /zen/ # Output: => yes
"zazen" =~ /zen/?"yes":"no" # Output: => yes
Os operadores de correspondência de padrões também são úteis para escrever instruções if mais curtas. Exemplo:
if meditation_type == "zazen" || meditation_type == "shikantaza" || meditation_type == "kinhin"
true
end
Can be rewritten as:
if meditation_type =~ /^(zazen|shikantaza|kinhin)$/
true
end
O operador! ~ É o oposto de = ~, retorna true quando não há correspondência e false se houver uma correspondência.
Mais informações estão disponíveis nesta postagem do blog .
"a" == "a"
,"a" === "a"
e"a".eql? "a"
. Mas isso é falso:"a".equal? "a"
(Minas é ruby 1.9.2-p180)