Project

General

Profile

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

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

View differences:

lib/set.rb
212 212
    return self if instance_of?(Set) && klass == Set && block.nil? && args.empty?
213 213
    klass.new(self, *args, &block)
214 214
  end
215
  alias to_st to_set
216

  
217
  private def _to_st?(e)
218
    if e.respond_to?(:to_st) && (s = e.to_st) && s.is_a?(Set)
219
      s
220
    end
221
  end
215 222

  
216 223
  def flatten_merge(set, seen = Set.new) # :nodoc:
217 224
    set.each { |e|
218
      if e.is_a?(Set)
225
      if s = _to_st?(e)
226
        e = s
219 227
        if seen.include?(e_id = e.object_id)
220 228
          raise ArgumentError, "tried to flatten recursive Set"
221 229
        end
......
241 249
  # Equivalent to Set#flatten, but replaces the receiver with the
242 250
  # result in place.  Returns nil if no modifications were made.
243 251
  def flatten!
244
    replace(flatten()) if any? { |e| e.is_a?(Set) }
252
    replace(flatten()) if any? { |e| _to_st?(e) }
245 253
  end
246 254

  
247 255
  # Returns true if the set contains the given object.
......
260 268
    case
261 269
    when set.instance_of?(self.class) && @hash.respond_to?(:>=)
262 270
      @hash >= set.instance_variable_get(:@hash)
263
    when set.is_a?(Set)
271
    when set = _to_st?(set)
264 272
      size >= set.size && set.all? { |o| include?(o) }
265 273
    else
266 274
      raise ArgumentError, "value must be a set"
......
273 281
    case
274 282
    when set.instance_of?(self.class) && @hash.respond_to?(:>)
275 283
      @hash > set.instance_variable_get(:@hash)
276
    when set.is_a?(Set)
284
    when set = _to_st?(set)
277 285
      size > set.size && set.all? { |o| include?(o) }
278 286
    else
279 287
      raise ArgumentError, "value must be a set"
......
286 294
    case
287 295
    when set.instance_of?(self.class) && @hash.respond_to?(:<=)
288 296
      @hash <= set.instance_variable_get(:@hash)
289
    when set.is_a?(Set)
297
    when set = _to_st?(set)
290 298
      size <= set.size && all? { |o| set.include?(o) }
291 299
    else
292 300
      raise ArgumentError, "value must be a set"
......
299 307
    case
300 308
    when set.instance_of?(self.class) && @hash.respond_to?(:<)
301 309
      @hash < set.instance_variable_get(:@hash)
302
    when set.is_a?(Set)
310
    when set = _to_st?(set)
303 311
      size < set.size && all? { |o| set.include?(o) }
304 312
    else
305 313
      raise ArgumentError, "value must be a set"
......
313 321
  #   Set[1, 2, 3].intersect? Set[4, 5]   #=> false
314 322
  #   Set[1, 2, 3].intersect? Set[3, 4]   #=> true
315 323
  def intersect?(set)
316
    set.is_a?(Set) or raise ArgumentError, "value must be a set"
324
    set = _to_st?(set) or raise ArgumentError, "value must be a set"
317 325
    if size < set.size
318 326
      any? { |o| set.include?(o) }
319 327
    else
......
503 511
      true
504 512
    elsif other.instance_of?(self.class)
505 513
      @hash == other.instance_variable_get(:@hash)
506
    elsif other.is_a?(Set) && self.size == other.size
514
    elsif (other = _to_st?(other)) && self.size == other.size
507 515
      other.all? { |o| @hash.include?(o) }
508 516
    else
509 517
      false
......
515 523
  end
516 524

  
517 525
  def eql?(o)   # :nodoc:
518
    return false unless o.is_a?(Set)
526
    return false unless o = _to_st?(o)
519 527
    @hash.eql?(o.instance_variable_get(:@hash))
520 528
  end
521 529

  
test/test_set.rb
5 5
class TC_Set < Test::Unit::TestCase
6 6
  class Set2 < Set
7 7
  end
8
  class ArraySet < Array
9
    def self.[](*v)
10
      new.concat(v)
11
    end
12
    alias to_st to_set
13
  end
8 14

  
9 15
  def test_aref
10 16
    assert_nothing_raised {
......
232 238
      set.superset?([2])
233 239
    }
234 240

  
241
    assert_equal(true, set.superset?(ArraySet[2]))
242

  
235 243
    [Set, Set2].each { |klass|
236 244
      assert_equal(true, set.superset?(klass[]), klass.name)
237 245
      assert_equal(true, set.superset?(klass[1,2]), klass.name)
......
261 269
      set.proper_superset?([2])
262 270
    }
263 271

  
272
    assert_equal(true, set.proper_superset?(ArraySet[2]))
273

  
264 274
    [Set, Set2].each { |klass|
265 275
      assert_equal(true, set.proper_superset?(klass[]), klass.name)
266 276
      assert_equal(true, set.proper_superset?(klass[1,2]), klass.name)
......
290 300
      set.subset?([2])
291 301
    }
292 302

  
303
    assert_equal(false, set.subset?(ArraySet[2]))
304

  
293 305
    [Set, Set2].each { |klass|
294 306
      assert_equal(true, set.subset?(klass[1,2,3,4]), klass.name)
295 307
      assert_equal(true, set.subset?(klass[1,2,3]), klass.name)
......
319 331
      set.proper_subset?([2])
320 332
    }
321 333

  
334
    assert_equal(false, set.proper_subset?(ArraySet[2]))
335

  
322 336
    [Set, Set2].each { |klass|
323 337
      assert_equal(true, set.proper_subset?(klass[1,2,3,4]), klass.name)
324 338
      assert_equal(false, set.proper_subset?(klass[1,2,3]), klass.name)
......
336 350
    case expected
337 351
    when true
338 352
      assert_send([set, :intersect?, other])
339
      assert_send([other, :intersect?, set])
353
      assert_send([other, :intersect?, set]) if other.is_a?(Set)
340 354
      assert_not_send([set, :disjoint?, other])
341
      assert_not_send([other, :disjoint?, set])
355
      assert_not_send([other, :disjoint?, set]) if other.is_a?(Set)
342 356
    when false
343 357
      assert_not_send([set, :intersect?, other])
344
      assert_not_send([other, :intersect?, set])
358
      assert_not_send([other, :intersect?, set]) if other.is_a?(Set)
345 359
      assert_send([set, :disjoint?, other])
346
      assert_send([other, :disjoint?, set])
360
      assert_send([other, :disjoint?, set]) if other.is_a?(Set)
347 361
    when Class
348 362
      assert_raise(expected) {
349 363
        set.intersect?(other)
......
361 375

  
362 376
    assert_intersect(ArgumentError, set, 3)
363 377
    assert_intersect(ArgumentError, set, [2,4,6])
378
    assert_intersect(true, set, ArraySet[2,4,6])
364 379

  
365 380
    assert_intersect(true, set, set)
366 381
    assert_intersect(true, set, Set[2,4])
......
617 632
    assert_equal(set1, set1)
618 633
    assert_equal(set1, set2)
619 634
    assert_not_equal(Set[1], [1])
635
    assert_equal(Set[1], ArraySet[1])
636
    assert_equal(false, Set[1].eql?([1]))
637
    assert_equal(true, Set[1].eql?(ArraySet[1]))
638
    assert_equal(false, Set[1] == [1])
639
    assert_equal(true, Set[1] == ArraySet[1])
620 640

  
621 641
    set1 = Class.new(Set)["a", "b"]
622 642
    set2 = Set["a", "b", set1]
623
-