|
|
|
#1 |
|
Messages: n/a
Hébergeur: |
How does Array#- (as in, [1, 2, 3, 1, 1] - [1]) compare two objects to
see if they are equal? I would think the .eql? method, but I've written a class that implements that method so that two different objects with the same values are considered equal and '-' isn't functioning as I would expect. A contrived example: irb(main):004:0> class Hash irb(main):005:1> def eql?(h) irb(main):006:2> true irb(main):007:2> end irb(main):008:1> end => nil irb(main):010:0> h1 = {'a' => 1} => {"a"=>1} irb(main):011:0> h2 = {'a' => 1} => {"a"=>1} irb(main):012:0> h1 == h2 => true irb(main):013:0> h1.eql? h2 => true irb(main):014:0> [h1] - [h2] => [{"a"=>1}] I would expect [] as a result, just like the following: irb(main):015:0> ["asdf"] - ["asdf"] => [] Thanks, Adam |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
On Monday 31 March 2008, Adam Bender wrote:
> How does Array#- (as in, [1, 2, 3, 1, 1] - [1]) compare two objects to > see if they are equal? I would think the .eql? method, but I've > written a class that implements that method so that two different > objects with the same values are considered equal and '-' isn't > functioning as I would expect. A contrived example: > > irb(main):004:0> class Hash > irb(main):005:1> def eql?(h) > irb(main):006:2> true > irb(main):007:2> end > irb(main):008:1> end > => nil > irb(main):010:0> h1 = {'a' => 1} > => {"a"=>1} > irb(main):011:0> h2 = {'a' => 1} > => {"a"=>1} > irb(main):012:0> h1 == h2 > => true > irb(main):013:0> h1.eql? h2 > => true > irb(main):014:0> [h1] - [h2] > => [{"a"=>1}] > > I would expect [] as a result, just like the following: > irb(main):015:0> ["asdf"] - ["asdf"] > => [] > > Thanks, > > Adam It uses eql?. However, before calling it, it calls the hash method of the two objects. If they return different values, they're considered different and eql? is not called. If the two calls to hash return the same values, then eql? is called. The reason is that two objects which are eql? should also have the same hash value (see the ri documentation for Object#hash) and the comparison of hash values is tried first because (I think) of efficiency. This make me think one should always follow this rule: "When you reimplement the eql? method, you should also reimplement the hash method (or at least, make sure the hash method returns the same value for objects which are eql?)" This is an example: class C attr_reader :x def initialize x @x = x end def hash @x.to_i end def eql? other self.class == other.class and @x.eql? other.x end end a = [ C.new(1), C.new(2)] p (a - [C.new(1)]) In this case, two objects of class C are eql? if their instance variables @x have the same value. Since hash returns @x (converted to an int), two objects which are eql? have hash methods which return the same value. I hope this s Stefano |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
2008/3/31, Adam Bender <abender@gmail.com>:
> How does Array#- (as in, [1, 2, 3, 1, 1] - [1]) compare two objects to > see if they are equal? I would think the .eql? method, but I've > written a class that implements that method so that two different > objects with the same values are considered equal and '-' isn't > functioning as I would expect. A contrived example: > > irb(main):004:0> class Hash > irb(main):005:1> def eql?(h) > irb(main):006:2> true > irb(main):007:2> end > irb(main):008:1> end > => nil > irb(main):010:0> h1 = {'a' => 1} > => {"a"=>1} > irb(main):011:0> h2 = {'a' => 1} > => {"a"=>1} > irb(main):012:0> h1 == h2 > => true > irb(main):013:0> h1.eql? h2 > => true > irb(main):014:0> [h1] - [h2] > => [{"a"=>1}] > > I would expect [] as a result, just like the following: > irb(main):015:0> ["asdf"] - ["asdf"] > => [] Another illustration of Stefano's point: irb(main):001:0> class Foo; end => nil irb(main):002:0> [Foo.new] - [Foo.new] => [#<Foo:0x7ff994b0>] irb(main):003:0> class Foo irb(main):004:1> def eql?(o) true end irb(main):005:1> end => nil irb(main):006:0> [Foo.new] - [Foo.new] => [#<Foo:0x7ff80988>] irb(main):007:0> class Foo irb(main):008:1> def hash;0 end irb(main):009:1> end => nil irb(main):010:0> [Foo.new] - [Foo.new] => [] Kind regards robert -- use.inject do |as, often| as.you_can - without end |
|
![]() |
| Outils de la discussion | |
|
|