Array#-

I need items to be compared based on their values, and not by object
equality, so I provide #== for the array elements. The problem is that I've
been trying to use Array#- as a set difference-like operation, and it
doesn't seem to respect any kind of user-provided means of defining
equality. A look into the Ruby source seems to indicate that it works by
populating a hash with the elements of the second array, then appending to
the result array if an element of the first array is in the hash. Does this
mean that it is impossible to get the behaviour I want from Array#- as it is
implemented?

Regards,

jogloran

jogloran wrote:

I need items to be compared based on their values, and not by object
equality, so I provide #== for the array elements. The problem is that I've
been trying to use Array#- as a set difference-like operation, and it
doesn't seem to respect any kind of user-provided means of defining
equality. A look into the Ruby source seems to indicate that it works by
populating a hash with the elements of the second array, then appending to
the result array if an element of the first array is in the hash. Does this
mean that it is impossible to get the behaviour I want from Array#- as it is
implemented?

Nope, you just need to redefine hash and alias == as eql?.

This will work:

def hash()
   # But it's a good idea to actually define this in a meaningful way so
   # that putting the object into hashes is efficient.
   0
end

alias :eql? :==

···

--
http://flgr.0x42.net/

You have to define #hash and #eql?:

RUBY_VERSION # => "1.8.4"
class X
  attr_reader :foo
  def initialize(foo); @foo = foo end
end

[X.new(1), X.new(2)] - [X.new(1)] # => [#<X:0xb7deaf94 @foo=1>, #<X:0xb7deaf80 @foo=2>]

X.new(1).hash # => -605071554
X.new(1).hash # => -605071594
class X
  def hash
    @foo.hash
  end
  def eql?(x)
    foo == x.foo
  end
end

[X.new(1), X.new(2)] - [X.new(1)] # => [#<X:0xb7dead50 @foo=2>]

···

On Thu, Apr 13, 2006 at 11:21:18PM +0900, jogloran wrote:

I need items to be compared based on their values, and not by object
equality, so I provide #== for the array elements. The problem is that I've
been trying to use Array#- as a set difference-like operation, and it
doesn't seem to respect any kind of user-provided means of defining
equality. A look into the Ruby source seems to indicate that it works by
populating a hash with the elements of the second array, then appending to
the result array if an element of the first array is in the hash. Does this
mean that it is impossible to get the behaviour I want from Array#- as it is
implemented?

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

Ah, thank you. But could this change in future versions? The fact that the
operation is backed by a hash operation is not mentioned in the
documentation.

Thanks

···

On 4/14/06, Mauricio Fernandez <mfp@acm.org> wrote:

On Thu, Apr 13, 2006 at 11:21:18PM +0900, jogloran wrote:
> I need items to be compared based on their values, and not by object
> equality, so I provide #== for the array elements. The problem is that
I've
> been trying to use Array#- as a set difference-like operation, and it
> doesn't seem to respect any kind of user-provided means of defining
> equality. A look into the Ruby source seems to indicate that it works by
> populating a hash with the elements of the second array, then appending
to
> the result array if an element of the first array is in the hash. Does
this
> mean that it is impossible to get the behaviour I want from Array#- as
it is
> implemented?

You have to define #hash and #eql?:

RUBY_VERSION # => "1.8.4"
class X
  attr_reader :foo
  def initialize(foo); @foo = foo end
end

[X.new(1), X.new(2)] - [X.new(1)] # => [#<X:0xb7deaf94
@foo=1>, #<X:0xb7deaf80 @foo=2>]

X.new(1).hash # => -605071554
X.new(1).hash # => -605071594
class X
  def hash
    @foo.hash
  end
  def eql?(x)
    foo == x.foo
  end
end

[X.new(1), X.new(2)] - [X.new(1)] # => [#<X:0xb7dead50
@foo=2>]

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

Why don't you just use a Set for storage of the values if that's what it is?

Kind regards

robert