summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-07 02:16:04 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2013-12-07 02:16:04 +0000
commit7416073cded9976e7b87d142cca79ce2b0fcc845 (patch)
tree21793d331381dad60abda6eb4394ccd211d3cbd6
parent77280b6cd66467c7ff7f04c4849dd4a5181d5397 (diff)
hash.c: rb_hash_reject without dup
* hash.c (rb_hash_reject): copy unrejected elements only to new hash, so that the change on the original receiver can affect. [ruby-core:58914] [Bug #9223] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@44047 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog6
-rw-r--r--hash.c18
-rw-r--r--test/ruby/test_enumerator.rb10
3 files changed, 30 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index 5f2a7302c3..57b11a164d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sat Dec 7 11:15:52 2013 Nobuyoshi Nakada <nobu@ruby-lang.org>
+
+ * hash.c (rb_hash_reject): copy unrejected elements only to new hash,
+ so that the change on the original receiver can affect.
+ [ruby-core:58914] [Bug #9223]
+
Sat Dec 7 08:25:00 2013 Richo Healey <richo@psych0tik.net>
* test/ruby/test_struct.rb: Add regression test for question marks and
diff --git a/hash.c b/hash.c
index 5ceac768c9..a52e02ff67 100644
--- a/hash.c
+++ b/hash.c
@@ -1092,6 +1092,15 @@ rb_hash_reject_bang(VALUE hash)
return hash;
}
+static int
+reject_i(VALUE key, VALUE value, VALUE hash)
+{
+ if (!RTEST(rb_yield_values(2, key, value))) {
+ rb_hash_aset(hash, key, value);
+ }
+ return ST_CONTINUE;
+}
+
/*
* call-seq:
* hsh.reject {| key, value | block } -> a_hash
@@ -1106,7 +1115,14 @@ rb_hash_reject_bang(VALUE hash)
static VALUE
rb_hash_reject(VALUE hash)
{
- return rb_hash_delete_if(rb_obj_dup(hash));
+ VALUE ret;
+
+ RETURN_SIZED_ENUMERATOR(hash, 0, 0, hash_enum_size);
+ ret = hash_alloc(rb_obj_class(hash));
+ if (!RHASH_EMPTY_P(hash)) {
+ rb_hash_foreach(hash, reject_i, ret);
+ }
+ return ret;
}
/*
diff --git a/test/ruby/test_enumerator.rb b/test/ruby/test_enumerator.rb
index e08edd512c..1d583e4fee 100644
--- a/test/ruby/test_enumerator.rb
+++ b/test/ruby/test_enumerator.rb
@@ -501,9 +501,13 @@ class TestEnumerator < Test::Unit::TestCase
def test_size_for_enum_created_from_hash
h = {a: 1, b: 2, c: 3}
- %i[delete_if reject! select select! keep_if each each_key each_pair].each do |method|
- assert_equal 3, h.send(method).size
- end
+ methods = %i[delete_if reject reject! select select! keep_if each each_key each_pair]
+ enums = methods.map {|method| h.send(method)}
+ s = enums.group_by(&:size)
+ assert_equal([3], s.keys, ->{s.reject!{|k| k==3}.inspect})
+ h[:d] = 4
+ s = enums.group_by(&:size)
+ assert_equal([4], s.keys, ->{s.reject!{|k| k==4}.inspect})
end
def test_size_for_enum_created_from_env