Set#== ain't..

G

Gary Shea

While writing an acceptance test, I needed to compare two sets of sets
of integers:

require 'set'
a = Set.new([Set.new([3,4]), Set.new([5,6])])
b = Set.new([Set.new([3,4]), Set.new([5,6])])
puts #{a == b}\n"

prints out 'false'.

Apparently the built-in Set library uses Hash#includes? to determine if
an object is in the rhs set. This method appears to use object id, so
set equality is based on set member object id.

A naive #==(set) that works the way I think it should is pretty simple:

def Set.my_eql?(set)
...
# this is the only part of my_eql? that differs from #==(set),
# replacing the line 'set.all? { |o| hash.include?(o) }'

set.all? { |o|
@hash.each_value do |my_o|
if my_o == o
last true
end
false
end
}
end

I'm sure this has come up before... is there a better solution? This
one is fine for my purposes, but I would be nice there was a packaged
solution out there.

Gary
 
D

David A. Black

Hi --

While writing an acceptance test, I needed to compare two sets of sets
of integers:

require 'set'
a = Set.new([Set.new([3,4]), Set.new([5,6])])
b = Set.new([Set.new([3,4]), Set.new([5,6])])
puts #{a == b}\n"

prints out 'false'.

Apparently the built-in Set library uses Hash#includes? to determine if
an object is in the rhs set. This method appears to use object id, so
set equality is based on set member object id.

A naive #==(set) that works the way I think it should is pretty simple:

def Set.my_eql?(set)

You'd want that to be an instance method, not a class method:

class Set
def my_eql?(set)
...
# this is the only part of my_eql? that differs from #==(set),
# replacing the line 'set.all? { |o| hash.include?(o) }'

set.all? { |o|
@hash.each_value do |my_o|
if my_o == o
last true
end
false
end
}
end

You could just do:

set.all? {|x| any? {|y| x == y } }
I'm sure this has come up before... is there a better solution? This
one is fine for my purposes, but I would be nice there was a packaged
solution out there.

It did come up, quite recently I think. I can't remember what the
consensus was, if any.


David
 
G

Gary Shea

Hi --

While writing an acceptance test, I needed to compare two sets of sets
of integers:

require 'set'
a = Set.new([Set.new([3,4]), Set.new([5,6])])
b = Set.new([Set.new([3,4]), Set.new([5,6])])
puts #{a == b}\n"

prints out 'false'.

Apparently the built-in Set library uses Hash#includes? to determine if
an object is in the rhs set. This method appears to use object id, so
set equality is based on set member object id.

A naive #==(set) that works the way I think it should is pretty simple:

def Set.my_eql?(set)

You'd want that to be an instance method, not a class method:

class Set
def my_eql?(set)

Whoops :)
You could just do:

set.all? {|x| any? {|y| x == y } }

Wow, that's almost mathematical set notation! Nice.
 
C

christophe.poucet

The above solution of set.all? {|x| any? { |y| x== y} } is not a full
solution. This will only work if you have set-nesting as described in
the original problem, but not if you have higher nesting (because then
you run back into the same original problem except one nesting level
down).

If this was the actual definition of ==, then it would work of course
:).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,167
Latest member
SusanaSwan
Top