Feature #3995 ยป hash_update.diff
| w/hash.c | ||
|---|---|---|
|
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
|
||
| ... | ... | |
|
* h2 = { "b" => 254, "c" => 300 }
|
||
|
* h1.merge!(h2) { |key, v1, v2| v1 }
|
||
|
* #=> {"a"=>100, "b"=>200, "c"=>300}
|
||
|
*
|
||
|
* If <i>other_hash</i> 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
|
||
|
* 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);
|
||
|
}
|
||
| w/include/ruby/ruby.h | ||
|---|---|---|
|
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);
|
||
| w/vm_eval.c | ||
|---|---|---|
|
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)
|
||
|
{
|
||