summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--NEWS4
-rw-r--r--lib/set.rb22
-rw-r--r--test/test_set.rb19
4 files changed, 48 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index c96a81a134..71133697d2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+Sat Nov 5 18:17:54 2016 Akinori MUSHA <knu@iDaemons.org>
+
+ * lib/set.rb (Set#compare_by_identity, Set#compare_by_identity?):
+ New methods. [Feature #12210]
+
Sat Nov 5 18:17:08 2016 SHIBATA Hiroshi <hsbt@ruby-lang.org>
* lib/rdoc/*, test/rdoc/*: Update rdoc-5.0.0
diff --git a/NEWS b/NEWS
index 439057a6e1..d9f6c6eedb 100644
--- a/NEWS
+++ b/NEWS
@@ -189,6 +189,10 @@ with all sufficient information, see the ChangeLog file or Redmine
* pathname
* New method: Pathname#empty? [Feature#12596]
+* set
+ * New methods: Set#compare_by_identity and Set#compare_by_identity?.
+ [Feature #12210]
+
* WEBrick
* Don't allow , as a separator [Bug #12791]
diff --git a/lib/set.rb b/lib/set.rb
index e77af5de2e..43c388ca90 100644
--- a/lib/set.rb
+++ b/lib/set.rb
@@ -3,7 +3,7 @@
#
# set.rb - defines the Set class
#++
-# Copyright (c) 2002-2013 Akinori MUSHA <knu@iDaemons.org>
+# Copyright (c) 2002-2016 Akinori MUSHA <knu@iDaemons.org>
#
# Documentation by Akinori MUSHA and Gavin Sinclair.
#
@@ -37,7 +37,8 @@
# Set uses Hash as storage, so you must note the following points:
#
# * Equality of elements is determined according to Object#eql? and
-# Object#hash.
+# Object#hash. Use Set#compare_by_identity to make a set compare
+# its elements by their identity.
# * Set assumes that the identity of each element does not change
# while it is stored. Modifying an element of a set will render the
# set to an unreliable state.
@@ -91,6 +92,23 @@ class Set
end
end
+ # Makes the set compare its elements by their identity and returns
+ # self. This method may not be supported by all subclasses of Set.
+ def compare_by_identity
+ if @hash.respond_to?(:compare_by_identity)
+ @hash.compare_by_identity
+ self
+ else
+ raise NotImplementedError, "#{self.class.name}\##{__method__} is not implemented"
+ end
+ end
+
+ # Returns true if the set will compare its elements by their
+ # identity. Also see Set#compare_by_identity.
+ def compare_by_identity?
+ @hash.respond_to?(:compare_by_identity?) && @hash.compare_by_identity?
+ end
+
def do_with_enum(enum, &block) # :nodoc:
if enum.respond_to?(:each_entry)
enum.each_entry(&block) if block
diff --git a/test/test_set.rb b/test/test_set.rb
index 9439974fea..07c404ab79 100644
--- a/test/test_set.rb
+++ b/test/test_set.rb
@@ -715,6 +715,25 @@ class TC_Set < Test::Unit::TestCase
set1.add(set2)
assert_equal(true, set1.inspect.include?('#<Set: {...}>'))
end
+
+ def test_compare_by_identity
+ a1, a2 = "a", "a"
+ b1, b2 = "b", "b"
+ c = "c"
+ array = [a1, b1, c, a2, b2]
+
+ iset = Set.new.compare_by_identity
+ assert_send([iset, :compare_by_identity?])
+ iset.merge(array)
+ assert_equal(5, iset.size)
+ assert_equal(array.map(&:object_id).sort, iset.map(&:object_id).sort)
+
+ set = Set.new
+ assert_not_send([set, :compare_by_identity?])
+ set.merge(array)
+ assert_equal(3, set.size)
+ assert_equal(array.uniq.sort, set.sort)
+ end
end
class TC_SortedSet < Test::Unit::TestCase