From: p.szmielew@... Date: 2016-12-27T08:34:31+00:00 Subject: [ruby-core:78856] [Ruby trunk Bug#12970] == Equality of recursive sets fails Issue #12970 has been updated by Piotr Szmielew. In this particular example even manually rehashing internal hash doesn't quite work... ~~~ ruby s = Set.new t = Set.new s << [s] t << [t] s == t # => false s.instance_variable_get(:@hash).rehash t.instance_variable_get(:@hash).rehash s == t # => false ~~~ So this isn't issue with rehashing, therefore my patch definitely wouldn't work here. There is another solution - when comparing sets, use hash method calculate hashes and compare them. Code would look like this: ~~~ ruby def ==(other) if self.equal?(other) true elsif other.instance_of?(self.class) @hash.keys.hash == other.instance_variable_get(:@hash).keys.hash elsif other.is_a?(Set) && self.size == other.size other.all? { |o| @hash.keys.map(&:hash).include?(o.hash) } else false end end ~~~ With this approach, examples you provided works correctly. Let me know if this acceptable solution and should I provide patch. Marc-Andre Lafortune wrote: > That's not going to cut it... There are many other counter examples.... > > ``` > s = Set.new > t = Set.new > s << [s] > t << [t] > s == t # => false > ``` > > or similarly: > > ``` > s = Set.new > t = Set.new > a = Set.new([s]) > b = Set.new([t]) > s << a > t << b > s == t # => false > ``` ---------------------------------------- Bug #12970: == Equality of recursive sets fails https://bugs.ruby-lang.org/issues/12970#change-62264 * Author: Kevin de Berk * Status: Open * Priority: Normal * Assignee: * Target version: * ruby -v: 2.2.5, 2.3.3 * Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN ---------------------------------------- Comparing recursive arrays and hashes with equal? contents (save for the recursive element) using == succeeds. However, using == to compare two recursive sets with equal? contents fails. I expect that to succeed. See the attached script. This is my output for 2.2.5 and 2.3.3: ~~~ [1, 2, 3] == [1, 2, 3]? -> true [1, 2, 3, [...]] == [1, 2, 3, [...]]? -> true {:a=>1, :b=>2} == {:a=>1, :b=>2}? -> true {:a=>1, :b=>2, :c=>{...}} == {:a=>1, :b=>2, :c=>{...}}? -> true #<Set:0x00000001f90fc8> == #<Set:0x00000001f90500>? -> true #<Set:0x00000001f92968> == #<Set:0x00000001f91478>? -> false ~~~ ---Files-------------------------------- recursive_set_comparison.rb (871 Bytes) fix_recursive_sets.patch (2.39 KB) -- https://bugs.ruby-lang.org/ Unsubscribe: <mailto:ruby-core-request@ruby-lang.org?subject=unsubscribe> <http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>