# Re: Ruby and Java equality usage

**URL:** <https://www.ruby-forum.com/t/re-ruby-and-java-equality-usage/96274>\
**Category:** Ruby\
**Created:** [June 27, 2006, 9:01pm UTC](https://www.ruby-forum.com/t/re-ruby-and-java-equality-usage/96274 "2006-06-27T21:01:01Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![MolitorS\_Stephen\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@MolitorS\_Stephen\_L](https://www.ruby-forum.com/u/MolitorS_Stephen_L)\
**Post date:** [June 27, 2006, 9:01pm UTC](https://www.ruby-forum.com/t/re-ruby-and-java-equality-usage/96274/1 "2006-06-27T21:01:01Z")

</div>

> > > > Jacob F. wrote:

> Is it true then that a.eql?(b) only if a.hash == b.hash?

Yes. But not necessarily the vice versa. If a.eql?(b) is true, then  
a.hash == b.hash must also be true. And if a.hash != b.hash, then  
a.eql?(b) is necessarily false. However if a.hash == b.hash, then  
a.eql?(b) may be true or false. (The above is all assuming proper  
implementations of hash and eql?.)

> What’s the damage in a.eql?(b) returning true when in different  
> buckets?

That will never happen. If a and b have different hashes then they go  
in different buckets. And if their hashes are different they are not  
equivalent (not eql?).

> Why doesn’t the default implementation of Object#eql? just use #==  
> internally?

Good question! Or to put it another way why do we need separate == and  
eql? methods? The only rationale I can think of is to completely  
separate the hash related methods (eql? and hash) from ==. So I can  
override == knowing that I won’t be changing hash behavior at all.  
Except that if I’m overriding == I would usually want to change the hash  
related behaviors to be consistent with my new concept of equivalence!

Steve

---

<div class="post-metadata">

**Author:** ![MolitorS\_Stephen\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@MolitorS\_Stephen\_L](https://www.ruby-forum.com/u/MolitorS_Stephen_L)\
**Post date:** [June 27, 2006, 10:50pm UTC](https://www.ruby-forum.com/t/re-ruby-and-java-equality-usage/96274/2 "2006-06-27T22:50:53Z")

</div>

On 6/27/06, Molitor, Stephen L [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > > > > Jacob F. wrote:
> 
> > Is it true then that a.eql?(b) only if a.hash == b.hash?
> 
> Yes. But not necessarily the vice versa. If a.eql?(b) is true, then  
> a.hash == b.hash must also be true. And if a.hash != b.hash, then  
> a.eql?(b) is necessarily false. However if a.hash == b.hash, then  
> a.eql?(b) may be true or false. (The above is all assuming proper  
> implementations of hash and eql?.)

I understand the “not vice versa” (that’s why I used “only if” in the  
clause above :). I’m still not convinced that a.eql?(b) must imply  
a.hash == b.hash. I’m willing to be convinced, but I haven’t heard yet  
an argument as to _why_ – only arguments along the lines of “that’s  
the way it is”. The way I see it, from looking through hash.c and st.c  
in the core, there is no contract on the value of a.eql?(b) when  
a.hash != b.hash. As far as I can tell, implementing MyClass#eql? as:

class MyClass  
def eql?(other)  
raise “Oops!” unless self.hash == other.hash  
return false  
end  
end

will never raise the exception in normal use of the Hash class (I’m  
assuming that people follow the rules and aren’t using eql?  
explicitly). That’s why I asked the following:

> > What’s the damage in a.eql?(b) returning true when in different  
> > buckets?
> 
> That will never happen. If a and b have different hashes then they go  
> in different buckets. And if their hashes are different they are not  
> equivalent (not eql?).

But it _will_ happen, if I don’t follow your definition of a “proper”  
implementation of eql?. I can understand the pushback in your second  
sentence. Semantically, it doesn’t make sense for two objects that  
claim to be eql? to be hashed into different buckets. But relying on  
the exclusive manner in which eql? is called, that shouldn’t matter

It’s the same as implementing a function (math) with a limited  
domain. What’s the output of the function (code) when I give it an  
invalid input? If I can guarantee that an invalid input will never be  
given, it doesn’t matter.

> > Why doesn’t the default implementation of Object#eql? just use #==  
> > internally?
> 
> Good question! Or to put it another way why do we need separate == and  
> eql? methods? The only rationale I can think of is to completely  
> separate the hash related methods (eql? and hash) from ==. So I can  
> override == knowing that I won’t be changing hash behavior at all.  
> Except that if I’m overriding == I would usually want to change the hash  
> related behaviors to be consistent with my new concept of equivalence!

I disagree that questioning the existence of eql? is the same as what  
I’m suggesting above. I understand perfectly well why eql? exists  
separate from ==. eql? serves exactly one purpose: determining whether  
two objects that get hashed into the same bucket should be considered  
the same key or a different key. I can understand as well that there  
are times when that determination will be separate from the  
determination of whether the objects are “equal” (==). So I do believe  
that the eql? method is necessary.

However, I don’t see why – apart from purity in the insistence that  
a.eql?(b) only if a.hash == b.hash – the _default_ behavior of eql?  
can’t be the same as ==. And since I only see that one reason –  
purity – this is my question:

Would it introduce bugs if a.eql?(b) were to return true when a.hash !=  
b.hash?

Jacob F.

---

<div class="post-metadata">

**Author:** ![MolitorS\_Stephen\_L](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/e480ec/32.png) [@MolitorS\_Stephen\_L](https://www.ruby-forum.com/u/MolitorS_Stephen_L)\
**Post date:** [June 27, 2006, 11:10pm UTC](https://www.ruby-forum.com/t/re-ruby-and-java-equality-usage/96274/3 "2006-06-27T23:10:14Z")

</div>

On Jun 27, 2006, at 2:59 PM, Molitor, Stephen L wrote:

> > Why doesn’t the default implementation of Object#eql? just use #==  
> > internally?
> 
> Good question! Or to put it another way why do we need separate ==  
> and  
> eql? methods? The only rationale I can think of is to completely  
> separate the hash related methods (eql? and hash) from ==.

Here is my take on the equality methods:

a.equal?(b) # identity: do a and b reference the same object?  
a.eql?(b) # representation: do a and b reference objects with the  
same value and same representation?  
a.==(b) # equivalence: do a and b reference objects with the same  
value regardless of representation?  
g.===(b) # membership: does b belong to the ‘group’ g?

3.eql?(3.0) is false because two different representations are  
being compared  
3 == 3.0 is true because the same value is represented by  
both objects  
0 == Complex(0,0) is true, same value, different representation

String === “s” is true because “s” is member of the collection of  
all Strings  
0…10 === 4 is true because 4 is a ‘member’ of the range  
/[ab]/ === ‘a’ is true because a is a ‘member’ of the strings  
matched by the re

There is also include? which is defined for quite a few classes and  
which is very  
similar to === in many cases.

Don’t forget the ‘=~’ operator which is like === but returns an index  
within the  
group, which is reminiscent of Array#index, for example.

It seems to me that with a little work, ===, =~, index, and include?  
semantics could be  
made a bit more uniform. For example:

```
s = Set.new [1,2,3]
s.include? 1 # true
s === 1 # false, why not behave like include? here

a = [:apple, :banana, :cherry]
a.index(:banana)	# 1
a =~ :banana # false (why not return 1?)

a.include?(:banana)	# true
a === :banana # false (why not return true?)

```

I suspect it might be difficult to avoid breaking existing code if  
these changes  
were made.

Gary W.
