Feature #15240 ยป set-duck-typing-15240.patch
| 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]
|
||