Array#uniq vs Array#-

(Clavius Tales) #1

Hi.

Do you know why?

Thanks.

(Gerald Bauer) #2

Hello,

   If you Google "ruby uniq" I get as the 2nd result the article:

   More than you care to know about the uniq method [1] by Chris Holz

that tells you with many code examples:

Multiple instances of the same classes (Object.new) are treated distinctly
and do not reduce to a single object in the returned array.

   Try:
   [Any,Any].uniq
   => [Any]

    that will work as you expect.

    Cheers. Prost.

[1] http://chrisholtz.com/blog/more-than-you-care-to-know-about-the-uniq-method/

(Gerald Bauer) #3

Hello,

   Just looked at the 1st result in the "ruby uniq" Google search,
that is, the official Array RDoc [1].

    If you look at Array#uniq it tells you:

It compares values using their hash and eql? methods for efficiency.

   If you try it. Add to your Any class:

   def hash() 1; end

   And retry:

  [Any.new,Any.new].uniq
  => [#<Any:0x111>]

    Now it works as you expect. Cheers. Prost.

[1] https://ruby-doc.org/core-2.5.0/Array.html#method-i-uniq

(Cristian Rivera) #4

It comes down to a matter of uniqueness. In the first part of your example `uniq` returns an Array with both elements because it uses the object hash AND `eql?` to determine uniqueness. In the last part of your example the `-` minus in Ruby removes all unique objects from the Arrays before actually performing the subtraction therefore giving you an empty Array. It removes the unique values between the two because you obviously can’t subtract two things that aren’t equal. Even though you are setting `eql?` in your class the object hash between the two still varies.

Thanks,
Cristian Rivera

···

On Apr 16, 2019, 5:30 PM -0400, Clavius Tales <claviustales@gmail.com>, wrote:
Hi.

https://repl.it/repls/FantasticIrritatingObjectcode

Do you know why?

Thanks.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

(Clavius Tales) #5

Hi, Gerald.

The RDoc also says that Array#- uses both #hash and #eql? methods. But
in my example I implemented just the #eql? method and worked:

[Any.new] - [Any.new]
=> []

In other words: why Array#- do not require that elements implement
#hash method for make equality comparison, as said in documentation?

Cheers.

···

On Tue, Apr 16, 2019 at 8:04 PM Gerald Bauer <gerald.bauer@gmail.com> wrote:

Hello,

   Just looked at the 1st result in the "ruby uniq" Google search,
that is, the official Array RDoc [1].

    If you look at Array#uniq it tells you:

> It compares values using their hash and eql? methods for efficiency.

   If you try it. Add to your Any class:

   def hash() 1; end

   And retry:

  [Any.new,Any.new].uniq
  => [#<Any:0x111>]

    Now it works as you expect. Cheers. Prost.

[1] https://ruby-doc.org/core-2.5.0/Array.html#method-i-uniq

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

(Clavius Tales) #6

Hi, Cristian.

In the last part of your example the `-` minus in Ruby removes all

unique objects from the Arrays before actually performing the subtraction
therefore giving you an empty Array. It removes the unique values between
the two because you obviously can’t subtract two things that aren’t equal.

From what I understand of what you said, it should be this:

[:a] - [:b]
=> []

[:a] - [1]
=> []

But it is:

[:a] - [:b]
=> [:a]

[:a] - [1]
=> [:a]

I've enhanced my example:
https://repl.it/repls/FantasticIrritatingObjectcode

Cheers.

···

On Tue, Apr 16, 2019 at 8:20 PM Cristian Rivera <cristian_rivera@me.com> wrote:

It comes down to a matter of uniqueness. In the first part of your example
`uniq` returns an Array with both elements because it uses the object hash
AND `eql?` to determine uniqueness. In the last part of your example the
`-` minus in Ruby removes all unique objects from the Arrays before
actually performing the subtraction therefore giving you an empty Array. It
removes the unique values between the two because you obviously can’t
subtract two things that aren’t equal. Even though you are setting `eql?`
in your class the object hash between the two still varies.

Thanks,
Cristian Rivera
On Apr 16, 2019, 5:30 PM -0400, Clavius Tales <claviustales@gmail.com>, > wrote:

Hi.

https://repl.it/repls/FantasticIrritatingObjectcode

Do you know why?

Thanks.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe
<ruby-talk-request@ruby-lang.org?subject=unsubscribe>>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

(Cristian Rivera) #7

Hi, I believe it removes all uniq objects of the same object type but I could be wrong. This is of course inferred by reading the .c source which I am not an expert at!

···

Sent from my iPhone

On Apr 16, 2019, at 7:46 PM, Clavius Tales <claviustales@gmail.com> wrote:

Hi, Cristian.

> In the last part of your example the `-` minus in Ruby removes all unique objects from the Arrays before actually performing the subtraction therefore giving you an empty Array. It removes the unique values between the two because you obviously can’t subtract two things that aren’t equal.

From what I understand of what you said, it should be this:

[:a] - [:b]
=> []

[:a] - [1]
=> []

But it is:

[:a] - [:b]
=> [:a]

[:a] - [1]
=> [:a]

I've enhanced my example:
https://repl.it/repls/FantasticIrritatingObjectcode

Cheers.

On Tue, Apr 16, 2019 at 8:20 PM Cristian Rivera <cristian_rivera@me.com> wrote:
It comes down to a matter of uniqueness. In the first part of your example `uniq` returns an Array with both elements because it uses the object hash AND `eql?` to determine uniqueness. In the last part of your example the `-` minus in Ruby removes all unique objects from the Arrays before actually performing the subtraction therefore giving you an empty Array. It removes the unique values between the two because you obviously can’t subtract two things that aren’t equal. Even though you are setting `eql?` in your class the object hash between the two still varies.

Thanks,
Cristian Rivera

On Apr 16, 2019, 5:30 PM -0400, Clavius Tales <claviustales@gmail.com>, wrote:
Hi.

https://repl.it/repls/FantasticIrritatingObjectcode

Do you know why?

Thanks.

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>

Unsubscribe: <mailto:ruby-talk-request@ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-talk>