Skip to content

Instantly share code, notes, and snippets.

@samflores
Last active January 26, 2024 17:41
Show Gist options
  • Save samflores/c99600d8db668aef9f9d4834d4131a96 to your computer and use it in GitHub Desktop.
Save samflores/c99600d8db668aef9f9d4834d4131a96 to your computer and use it in GitHub Desktop.

de forma geral, a convenção é que em Ruby o == compara se dois objetos tem o mesmo valor, não que são a mesma instância, como acontece em Java. Esse valor pode ser depender do domínio da sua aplicação, mas eu costumo pensar "esses 2 objetos tem a mesma representação em memória?". De novo, em geral. Existem exceções quando isso faz sentido.

'1' == 1 # é falso, pq o valor de '1' em memória seria o encoding desse caractere em unicode/ascii (49) e não 1
false == 0 # é falso, pq o tipo "boolean" é _como se fosse_ um enum que só aceita os valores true e false
# um exemplo que foge a regra, mas "faz sentido" (de acordo com o Rails team), assumindo que User é um model do Rails
u1 = User.new(id: 1, username: 'john.doe')
u2 = User.new(id: 1, username: 'joao.silva')
# pq do ponto de vista do AR dois objetos com o mesmo id representam o mesmo registro, já que se eu salvar os 2 no banco um vai sobrescrever o outro

o === checa se o objeto "aceita" o outro como um similar ou membro. a definição de aceitar é que muda de uma classe pra outra

Integer === 1 # a classe Integer aceita o valor 1 como um de seus items? é o mesmo que 1.is_a?(Integer)
String === '1' # 1.is_a?(String)
/\d+/ === '123' # /\d+/.match?('123')
(1..10) === 5 # (1..10).include?(5)

Percebam que os objetos da esquerda representam sempre o que eu gosto de chamar "categorias" de coisas, uma classe, uma regex ou um range. O único caso que me lembro onde isso pode causar uma certa confusão é para arrays. [1, 2, 3] === 2 vai retornar false. Isso é uma decisão de implementação por causa de como a linguagem usa o case statement (análogo do switch de outras linguagens), mas não vou entrar em detalhes (se quiserem saber, me pinguem). Quando o objeto da esquerda não é uma "categoria" de coisas, o === se comporta como o ==.

'1' === 1 # ainda é falso

O que eu quis dizer com "eles podem fazer o que raios o programador quiser" é que em Ruby os operadores são métodos, como quaiquer outros,:

class User
  def ==(other)
    self.id == other.id
  end

  def ===(other)
    self == other
  end
end

# inclusive podem ser chamados como qualquer outro método
u1 = User.new(id: 1)
u2 = User.new(id: 3)
u1.==(u2) # é a mesma coisa que u1 == u2
u2.===(u1) # é a mesma coisa que u2 === u1

É por isso que Integer === 1 é true, mas 1 === Integer é false. O objeto da esquerda no primeiro caso é uma instância da classe Class e a implementação de == lá usa a ideia de "categorias" e no segundo caso, o objeto da esquerda é uma instância de Integer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment