Project

General

Profile

Feature #15240 ยป set-duck-typing-15240.patch

jeremyevans0 (Jeremy Evans), 08/27/2019 08:10 PM

View differences:

lib/set.rb
return self if instance_of?(Set) && klass == Set && block.nil? && args.empty?
klass.new(self, *args, &block)
end
alias to_st to_set
private def _to_st?(e)
if e.respond_to?(:to_st) && (s = e.to_st) && s.is_a?(Set)
s
end
end
def flatten_merge(set, seen = Set.new) # :nodoc:
set.each { |e|
if e.is_a?(Set)
if s = _to_st?(e)
e = s
if seen.include?(e_id = e.object_id)
raise ArgumentError, "tried to flatten recursive Set"
end
......
# Equivalent to Set#flatten, but replaces the receiver with the
# result in place. Returns nil if no modifications were made.
def flatten!
replace(flatten()) if any? { |e| e.is_a?(Set) }
replace(flatten()) if any? { |e| _to_st?(e) }
end
# Returns true if the set contains the given object.
......
case
when set.instance_of?(self.class) && @hash.respond_to?(:>=)
@hash >= set.instance_variable_get(:@hash)
when set.is_a?(Set)
when set = _to_st?(set)
size >= set.size && set.all? { |o| include?(o) }
else
raise ArgumentError, "value must be a set"
......
case
when set.instance_of?(self.class) && @hash.respond_to?(:>)
@hash > set.instance_variable_get(:@hash)
when set.is_a?(Set)
when set = _to_st?(set)
size > set.size && set.all? { |o| include?(o) }
else
raise ArgumentError, "value must be a set"
......
case
when set.instance_of?(self.class) && @hash.respond_to?(:<=)
@hash <= set.instance_variable_get(:@hash)
when set.is_a?(Set)
when set = _to_st?(set)
size <= set.size && all? { |o| set.include?(o) }
else
raise ArgumentError, "value must be a set"
......
case
when set.instance_of?(self.class) && @hash.respond_to?(:<)
@hash < set.instance_variable_get(:@hash)
when set.is_a?(Set)
when set = _to_st?(set)
size < set.size && all? { |o| set.include?(o) }
else
raise ArgumentError, "value must be a set"
......
# Set[1, 2, 3].intersect? Set[4, 5] #=> false
# Set[1, 2, 3].intersect? Set[3, 4] #=> true
def intersect?(set)
set.is_a?(Set) or raise ArgumentError, "value must be a set"
set = _to_st?(set) or raise ArgumentError, "value must be a set"
if size < set.size
any? { |o| set.include?(o) }
else
......
true
elsif other.instance_of?(self.class)
@hash == other.instance_variable_get(:@hash)
elsif other.is_a?(Set) && self.size == other.size
elsif (other = _to_st?(other)) && self.size == other.size
other.all? { |o| @hash.include?(o) }
else
false
......
end
def eql?(o) # :nodoc:
return false unless o.is_a?(Set)
return false unless o = _to_st?(o)
@hash.eql?(o.instance_variable_get(:@hash))
end
test/test_set.rb
class TC_Set < Test::Unit::TestCase
class Set2 < Set
end
class ArraySet < Array
def self.[](*v)
new.concat(v)
end
alias to_st to_set
end
def test_aref
assert_nothing_raised {
......
set.superset?([2])
}
assert_equal(true, set.superset?(ArraySet[2]))
[Set, Set2].each { |klass|
assert_equal(true, set.superset?(klass[]), klass.name)
assert_equal(true, set.superset?(klass[1,2]), klass.name)
......
set.proper_superset?([2])
}
assert_equal(true, set.proper_superset?(ArraySet[2]))
[Set, Set2].each { |klass|
assert_equal(true, set.proper_superset?(klass[]), klass.name)
assert_equal(true, set.proper_superset?(klass[1,2]), klass.name)
......
set.subset?([2])
}
assert_equal(false, set.subset?(ArraySet[2]))
[Set, Set2].each { |klass|
assert_equal(true, set.subset?(klass[1,2,3,4]), klass.name)
assert_equal(true, set.subset?(klass[1,2,3]), klass.name)
......
set.proper_subset?([2])
}
assert_equal(false, set.proper_subset?(ArraySet[2]))
[Set, Set2].each { |klass|
assert_equal(true, set.proper_subset?(klass[1,2,3,4]), klass.name)
assert_equal(false, set.proper_subset?(klass[1,2,3]), klass.name)
......
case expected
when true
assert_send([set, :intersect?, other])
assert_send([other, :intersect?, set])
assert_send([other, :intersect?, set]) if other.is_a?(Set)
assert_not_send([set, :disjoint?, other])
assert_not_send([other, :disjoint?, set])
assert_not_send([other, :disjoint?, set]) if other.is_a?(Set)
when false
assert_not_send([set, :intersect?, other])
assert_not_send([other, :intersect?, set])
assert_not_send([other, :intersect?, set]) if other.is_a?(Set)
assert_send([set, :disjoint?, other])
assert_send([other, :disjoint?, set])
assert_send([other, :disjoint?, set]) if other.is_a?(Set)
when Class
assert_raise(expected) {
set.intersect?(other)
......
assert_intersect(ArgumentError, set, 3)
assert_intersect(ArgumentError, set, [2,4,6])
assert_intersect(true, set, ArraySet[2,4,6])
assert_intersect(true, set, set)
assert_intersect(true, set, Set[2,4])
......
assert_equal(set1, set1)
assert_equal(set1, set2)
assert_not_equal(Set[1], [1])
assert_equal(Set[1], ArraySet[1])
assert_equal(false, Set[1].eql?([1]))
assert_equal(true, Set[1].eql?(ArraySet[1]))
assert_equal(false, Set[1] == [1])
assert_equal(true, Set[1] == ArraySet[1])
set1 = Class.new(Set)["a", "b"]
set2 = Set["a", "b", set1]
    (1-1/1)