# Set and Object equivilence

**URL:** <https://www.ruby-forum.com/t/set-and-object-equivilence/122879>\
**Category:** Ruby\
**Created:** [December 12, 2007, 7:11pm UTC](https://www.ruby-forum.com/t/set-and-object-equivilence/122879 "2007-12-12T19:11:36Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [December 12, 2007, 7:11pm UTC](https://www.ruby-forum.com/t/set-and-object-equivilence/122879/1 "2007-12-12T19:11:36Z")

</div>

Hi,

I’ve just started with Ruby from Java, and am having trouble getting a  
set to recognise equivalence between objects. Basically it is adding  
multiple equal objects to the set.

I have created a class and overridden all of the operators \<=\> , ==,  
\<, \>, eqls?, equals?, hash to indicate that it should use an internal  
variable to compare.

Please find enclosed a unit test, the object, and the output from the  
test. Cool language BTW. Really enjoying it up until this moment. I’m  
probably missing some subtlety of the language.

Any help greatly appreciated.  
-------- source starts --------

require “test/unit”  
require “set”

class JunkTest \< Test::Unit::TestCase  
def test\_arraysMuckingAroundWith  
a = Thingy.new(1)  
b = Thingy.new(2)  
c = Thingy.new(1)  
d=Set.new  
d \<\< a  
d \<\< b  
d \<\< c  
puts “output set, with duplicates - the first 2 object should  
be equivilent” + d.sort.to\_s  
end  
end

class Thingy

```
attr_accessor :value

def <=> (thing)
    self.value <=> thing.value
end

def == (thing)
    self.value == thing.value
end

def > (thing)
    self.value > thing.value
end

def < (thing)
    self.value < thing.value
end

def eqls? (thing)
    self.value.eqls?(thing.value)
end

def equals? (thing)
    self.value.equals?(thing.value)
end

def initialize(val)
    @value = val
end

def hash
    puts "hash " + @value.hash.to_s
    @value.hash
end

def to_s
    value.to_s + ", "
end

```

end  
-------- source ends --------

-------- output starts --------

C:\dev\ruby\bin\ruby.exe -e  
“STDOUT.sync=true;STDERR.sync=true;load($0=ARGV.shift)” C:/projects/  
SearchJars/test/JunkTest.rb --name test\_arraysMuckingAroundWith  
Loaded suite C:/projects/SearchJars/test/JunkTest  
Started  
hash 3  
hash 5  
hash 3  
output set, with duplicates - 1, 1, 2,  
.  
Finished in 0.0 seconds.

1 tests, 0 assertions, 0 failures, 0 errors

Process finished with exit code 0

-------- output ends --------

Regards

Andrew Oxenburgh

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [December 12, 2007, 7:11pm UTC](https://www.ruby-forum.com/t/set-and-object-equivilence/122879/2 "2007-12-12T19:11:38Z")

</div>

2007/12/11, removed\_email\_address@domain.invalid [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> Please find enclosed a unit test, the object, and the output from the  
> def test\_arraysMuckingAroundWith  
> end  
> self.value == thing.value  
> def eqls? (thing)  
> Spelling error: this method needs to read “eql?”. This is likely the  
> cause for your issue.

> output set, with duplicates - 1, 1, 2,  
> .  
> Finished in 0.0 seconds.
> 
> 1 tests, 0 assertions, 0 failures, 0 errors
> 
> Process finished with exit code 0
> 
> -------- output ends --------

It seems the output does not stem from the code you present because  
the print statement looks different.

Few remarks: you can make your life easier by including Comparable and  
only implementing \<=\>; then \<, \<=, \> and \>= will be automatically be  
derived.

You can make your life even simpler by just doing

Thing = Struct.new :value

Cheers

robert

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [December 12, 2007, 7:13pm UTC](https://www.ruby-forum.com/t/set-and-object-equivilence/122879/3 "2007-12-12T19:13:27Z")

</div>

On Dec 11, 2007, at 10:07 AM, removed\_email\_address@domain.invalid wrote:

> ```
> def eqls? (thing)
> self.value.eqls?(thing.value)
> end
> 
> ```

You’ve got the name wrong, it should be eql?(thing).

> ```
> def equals? (thing)
> self.value.equals?(thing.value)
> end
> 
> ```

You probably mean equal?(thing), but you should never redefine  
equal?(x) anyway as it always assumed to be an object identity  
test.

Gary W.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [December 12, 2007, 7:26pm UTC](https://www.ruby-forum.com/t/set-and-object-equivilence/122879/4 "2007-12-12T19:26:36Z")

</div>

Hi Andrew,

First, change your .eqls? method to .eql? and that will fix your code.

Also, you should look into the Comparable mix-in module. Basically,  
if you define the spaceship operator (\<=\>) and include Comparable in  
your class, it will define it will define all the relational operators  
(==, \<, \<=, \>, \>=) and between? for you. Plus, != is internally  
implemented as the boolean negation of ==, so you get that also.

For Set member equality, two methods are used – eql? and hash.

Eric

====

On-site, hands-on Ruby training is available from [http://LearnRuby.com](http://LearnRuby.com)  
!

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [December 12, 2007, 7:37pm UTC](https://www.ruby-forum.com/t/set-and-object-equivilence/122879/5 "2007-12-12T19:37:52Z")

</div>

Thanks. Bit embarrassed with a simple spelling error. I looked at it  
for ages, and tried all sorts of permutations and combinations of set  
c’strs and adding methods!

I’ll check out the Comparable mixin as well.

Regards
