Returns a new array by removing duplicate values in _arr_, where
duplicates are detected by comparing using +eql?+.
Given that say I have a simple class:
class PossibleTime
attr_reader :day, :start_time, :end_time
def initialize(day, start_time, end_time)
@day, @start_time, @end_time = day, start_time, end_time
end
def hash
"#@day #@start_time #@end_time"
end
def ==(other_pt)
self.hash == other_pt.hash
end
def eql?(other_pt)
self == other_pt
end
end
Here +eql?+ is defined in terms of +==+. Creating two example instances shows
these methods working:
> a = PossibleTime.new('M', '9:30', '10:30')
> b = PossibleTime.new('M', '9:30', '10:30')
> c = PossibleTime.new('T', '9:30', '12:00')
> a == b
=> true
> a.eql? b
=> true
> a == c
=> false
> [a,b].uniq.size
=> 2
> # I was expecting 1, not 2
I'll add debugging to see if +eql?+ was even called:
class PossibleTime
def eql?(other_pt)
puts 'eql? called'
self == other_pt
end
end
> a.eql? b
eql? called
=> true
> a.eql? c
eql? called
=> false
> [a,b].uniq.size
=> 2
So eql? isn't even being called.
Am I overlooking something? Specifying something incorrectly? Not
understanding the fundamental interaction between eql? and uniq?
Thanks for your time,
marcel
--
Marcel Molina Jr. <mar...@vernix.org>
In message "Re: Customizing Array#uniq by defining eql?"
on Tue, 8 Mar 2005 05:16:17 +0900, "Marcel Molina Jr." <mar...@vernix.org> writes:
|PickAxe II's documentation for Array#uniq says,
|
| Returns a new array by removing duplicate values in _arr_, where
| duplicates are detected by comparing using +eql?+.
It creates hash internally to remove redundant values, so that
comparison is done by "eql?" but it is filtered by "hash" value first.
In other words, when you redefine "eql?" you have to redefine "hash"
as well.
matz.
Thanks for the reply. Yes, indeed, I had noted that I needed to define
both hash and eql?. I assumed that that was all that was needed for
uniq to work as expected.
The pertinent bits of code from the example I posted in the original email
are as follows:
def hash
"#@day #@start_time #@end_time"
end
def ==(other_pt)
self.hash == other_pt.hash
end
def eql?(other_pt)
self == other_pt
end
And yet eql? doesn't even seem to be called.
I agree that this is misleading. Can we clarify this in the
documentation please?
Regards,
Dan
In message "Re: Customizing Array#uniq by defining eql?"
on Tue, 8 Mar 2005 11:32:37 +0900, "Marcel Molina Jr." <mar...@vernix.org> writes:
|Thanks for the reply. Yes, indeed, I had noted that I needed to define
|both hash and eql?. I assumed that that was all that was needed for
|uniq to work as expected.
hash method should return integer value.
matz.