[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Set and Object equivilence

andrew.oxenburgh

12/11/2007 3:05:00 PM

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
4 Answers

Gary Wright

12/11/2007 3:16:00 PM

0


On Dec 11, 2007, at 10:07 AM, andrew.oxenburgh@gmail.com 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 Wright

Robert Klemme

12/11/2007 3:16:00 PM

0

2007/12/11, andrew.oxenburgh@gmail.com <andrew.oxenburgh@gmail.com>:
> 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)

Spelling error: this method needs to read "eql?". This is likely the
cause for your issue.

> 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 --------

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

--
use.inject do |as, often| as.you_can - without end

Eric I.

12/11/2007 3:30:00 PM

0

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://Lea...
!

andrew.oxenburgh

12/11/2007 3:35:00 PM

0

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


On Dec 11, 3:30 pm, "Eric I." <rubytrain...@gmail.com> wrote:
> 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 fromhttp://Lea...
> !