$B$J$+$@$G$9!#(B
$B:#$N$H$3$m(BHash#update$B$O(BHash$B$7$+<u$1IU$1$^$;$s$,!"(BEnumerable$B$^$G(B
$B<u$1IU$1$k$h$&$K3HD%$9$k$N$O$I$&$G$7$g$&$+!#(B
diff --git i/hash.c w/hash.c
index 873219a…8d0c72a 100644
— i/hash.c
+++ w/hash.c
@@ -1748,6 +1748,45 @@ rb_hash_update_block_i(VALUE key, VALUE value,
VALUE hash)
return ST_CONTINUE;
}
+static VALUE
+rb_enum_update_i(VALUE obj, VALUE hash, int argc, VALUE *argv)
+{
- if (argc == 1 && RB_TYPE_P(obj, T_ARRAY)) {
- argc = RARRAY_LEN(obj);
- argv = RARRAY_PTR(obj);
- }
- if (argc == 2) {
- st_insert(RHASH(hash)->ntbl, argv[0], argv[1]);
- }
- return Qnil;
+}
+static VALUE
+rb_enum_update_block_i(VALUE obj, VALUE hash, int argc, VALUE *argv)
+{
- VALUE key, value = Qundef, oldval;
- if (argc == 1 && RB_TYPE_P(obj, T_ARRAY)) {
- argc = RARRAY_LEN(obj);
- argv = RARRAY_PTR(obj);
- }
- switch (argc) {
-
case 2:
- value = argv[1];
-
case 1:
- key = argv[0];
- oldval = rb_hash_lookup2(hash, key, Qundef);
- if (oldval != Qundef) {
-
value = rb_yield_values(argc + 1, key, oldval, value);
- }
- else if (value == Qundef) {
-
value = rb_yield(key);
- }
- st_insert(RHASH(hash)->ntbl, key, value);
- break;
- }
- return Qnil;
+}
/*
- call-seq:
-
hsh.merge!(other_hash) -> hsh
@@ -1769,13 +1808,36 @@ rb_hash_update_block_i(VALUE key, VALUE value,
VALUE hash)
-
h2 = { "b" => 254, "c" => 300 }
-
h1.merge!(h2) { |key, v1, v2| v1 }
-
#=> {"a"=>100, "b"=>200, "c"=>300}
-
-
- If other_hash is not a Hash but an Enumerable, its #each
-
- method should yield [key, newval] pairs or mere key. In the latter
-
- case, thegiven block is always called regardless oldval, but
without
- case, thegiven block is always called regardless oldval, but
-
- newval.
-
-
-
h1 = { "a" => 100, "b" => 200 }
-
-
-
e1 = [["b", 254], ["c", 300]]
-
-
-
h1.merge!(e1) { |key, *v| v }
-
-
-
#=> {"a"=>100, "b"=>[200,254], "c"=>300}
-
-
-
-
h1 = { "a" => 100, "b" => 200 }
-
-
-
e1 = [["b"], ["c"]]
-
-
-
h1.merge!(e1) { |key, v1, v2| v1 }
-
-
-
#=> {"a"=>100, "b"=>[200], "c"=>[]}
-
static VALUE
rb_hash_update(VALUE hash1, VALUE hash2)
{
- VALUE tmp;
rb_hash_modify(hash1);
- hash2 = to_hash(hash2);
- tmp = rb_check_hash_type(hash2);
- if (NIL_P(tmp)) {
- VALUE (*bfunc)(ANYARGS) = rb_block_given_p() ?
-
rb_enum_update_block_i : rb_enum_update_i;
- rb_each_call(hash2, 0, 0, bfunc, hash1);
- return hash1;
- }
- hash2 = tmp;
if (rb_block_given_p()) {
rb_hash_foreach(hash2, rb_hash_update_block_i, hash1);
}
diff --git i/include/ruby/ruby.h w/include/ruby/ruby.h
index 4a3e0ff…aa7808b 100644
— i/include/ruby/ruby.h
+++ w/include/ruby/ruby.h
@@ -1164,6 +1164,7 @@ PRINTF_ARGS(void rb_compile_warn(const char ,
int, const char, …), 3, 4);
typedef VALUE rb_block_call_func(VALUE, VALUE, int, VALUE*);
VALUE rb_each(VALUE);
+VALUE rb_each_call(VALUE,int,VALUE*,VALUE(*)(ANYARGS),VALUE);
VALUE rb_yield(VALUE);
VALUE rb_yield_values(int n, …);
VALUE rb_yield_values2(int n, const VALUE *argv);
diff --git i/vm_eval.c w/vm_eval.c
index 05fd3fa…6f93897 100644
— i/vm_eval.c
+++ w/vm_eval.c
@@ -947,6 +947,12 @@ rb_each(VALUE obj)
return rb_call(obj, idEach, 0, 0, CALL_FCALL);
}
+VALUE
+rb_each_call(VALUE obj, int argc, VALUE *argv, VALUE
(*bl_proc)(ANYARGS), VALUE arg)
+{
- return rb_block_call(obj, idEach, argc, argv, bl_proc, arg);
+}
static VALUE
eval_string_with_cref(VALUE self, VALUE src, VALUE scope, NODE *cref,
const char *volatile file, volatile int line)
{