I have a class roughly like this:
class C
attr_accessor :board # board is a multidimensional array (represents a matrix)
def initialize
@board = ... # initialize board
end
def ==(other)
@board == other.board
end
end
Still, when I do:
s = Set.new
s.add(C.new)
s.include?(C.new) # => false
Why?
Set
uses eql?
and hash
, not ==
, to test two objects for equality. See, for example, this documentation of Set: "The equality of each couple of elements is determined according to Object#eql? and Object#hash, since Set uses Hash as storage."
If you want two different C
objects to be the same for set membership, you'll have to override those two methods.
class C
attr_accessor :board
def initialize
@board = 12
end
def eql?(other)
@board == other.board
end
def hash
@board.hash
end
end
s = Set.new
s.add C.new
s.include? C.new # => true
You need to do something below :
require 'set'
class C
attr_accessor :board
def initialize
@board = 12
end
def ==(other)
@board == other.board
end
end
s = Set.new
c = C.new
s.add(c)
s.include? c # => true
The reason below will not work:
s.add(C.new)
s.include?(C.new) # => false
Using C.new
you create 2 different objects. If you do run C.new
thrice then you will get 3 different objects:
C.new.object_id # => 74070710
C.new.object_id # => 74070360
C.new.object_id # => 74070030
Summary : The instance of C you added to s
,using Set#add
and the instance of C you are checking using Set#include?
are 2 different objects. So the result you got is more obvious.
class C
attr_accessor :board # board is a multidimensional array (represents a matrix)
def initialize
board = [[1],[2]] # initialize board
p @board #=> nil !!
end
def ==(other)
@board == other.board
end
def eql?(other) # not used
puts "eql? called"
@board == other.board
end
def ==(other) # not used
puts "== called"
@board == other.board
end
def hash
puts "hash called"
board.hash
end
end
require 'set'
s = Set.new
s.add(c = C.new)
p s.include?(c)
Set uses a Hash as storage underneath. Output:
nil
hash called
hash called
true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With