[前][次][番号順一覧][スレッド一覧]

ruby-changes:31968

From: nobu <ko1@a...>
Date: Sat, 7 Dec 2013 11:16:11 +0900 (JST)
Subject: [ruby-changes:31968] nobu:r44047 (trunk): hash.c: rb_hash_reject without dup

nobu	2013-12-07 11:16:04 +0900 (Sat, 07 Dec 2013)

  New Revision: 44047

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=44047

  Log:
    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]

  Modified files:
    trunk/ChangeLog
    trunk/hash.c
    trunk/test/ruby/test_enumerator.rb
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 44046)
+++ ChangeLog	(revision 44047)
@@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sat Dec  7 11:15:52 2013  Nobuyoshi Nakada  <nobu@r...>
+
+	* 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@p...>
 
 	* test/ruby/test_struct.rb: Add regression test for question marks and
Index: hash.c
===================================================================
--- hash.c	(revision 44046)
+++ hash.c	(revision 44047)
@@ -1092,6 +1092,15 @@ rb_hash_reject_bang(VALUE hash) https://github.com/ruby/ruby/blob/trunk/hash.c#L1092
     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) https://github.com/ruby/ruby/blob/trunk/hash.c#L1115
 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;
 }
 
 /*
Index: test/ruby/test_enumerator.rb
===================================================================
--- test/ruby/test_enumerator.rb	(revision 44046)
+++ test/ruby/test_enumerator.rb	(revision 44047)
@@ -501,9 +501,13 @@ class TestEnumerator < Test::Unit::TestC https://github.com/ruby/ruby/blob/trunk/test/ruby/test_enumerator.rb#L501
 
   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

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]