From: styrmis@... Date: 2018-03-21T14:26:57+00:00 Subject: [ruby-core:86241] [Ruby trunk Bug#14263] Array Intersection does not seem to use hash Issue #14263 has been updated by styrmis (Stefan Magnuson). File test-14264.rb added We (myself and [Lewis Buckley](https://github.com/lewispb)) investigated this issue as part of the Ruby Hack Day at Cookpad. We were able to replicate the issue on Ruby 2.6 (trunk)���digging a bit deeper we found that the unexpected behaviour only occurs when both arrays have <= 16 elements. This is because in Ruby 2.5 a [performance enhancement was added](https://bugs.ruby-lang.org/issues/13884) to avoid building a hash when the array sizes are small. The [version for small arrays](https://github.com/ruby/ruby/blob/trunk/array.c#L4230) compares elements [using `#eql?`](https://github.com/ruby/ruby/blob/trunk/array.c#L4230) whereas the implementation in 2.4 [defers to the `Hash` implementation of equality checking](https://github.com/ruby/ruby/blob/trunk/array.c#L4246) which appears to use the hash directly (and not the `#eql?` method). We discussed with Matz during the event, and the conclusion at the time was that: - The example as given has an inconsistent implementation (between the implementation of `Val#eql?` and `Val#hash`), and as such the behaviour is undefined, and could reasonably change between versions - The documentation for [`Object#eql?`](https://ruby-doc.org/core-2.5.0/Object.html#method-i-eql-3F) could be extended to make this clearer So one possible improvement would be to update the documentation for `Object#eql?` to make clear that when `#eql?` is overridden it should be kept consistent with the result of a comparison of the `#hash` of two objects. Another possible solution might be to make both variants (for both large and small arrays) use the same method of comparison, i.e. both `#eql?` or both hash equivalence. ---------------------------------------- Bug #14263: Array Intersection does not seem to use hash https://bugs.ruby-lang.org/issues/14263#change-71142 * Author: gkellogg (Gregg Kellogg) * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: 2.5.0 * Backport: 2.3: UNKNOWN, 2.4: UNKNOWN, 2.5: UNKNOWN ---------------------------------------- According to the documentation for Array#&, comparison is done using hash and eql? However, this does not seem to be the case in 2.5.0. If two instances are .eql? but their hashes are not, an array & should be empty: ~~~ ruby ([Var.new('a')] & [Var.new('b')]).empty? ~~~ This test works in 2.4.2 (and all earlier versions), but fails in 2.5.0. See attached script. ---Files-------------------------------- array_intersection.rb (535 Bytes) test-14264.rb (956 Bytes) -- https://bugs.ruby-lang.org/ Unsubscribe: