Project

General

Profile

Feature #8246 ยป 275.patch

zzak (zzak _), 04/11/2013 08:03 AM

View differences:

hash.c
/*
* call-seq:
* hsh.traverse(*keys) => obj
* hsh.traverse(*keys) {| key | block } => obj
*
* Traverses the hash and returns a value for the given key. If the key can't be
* found, there are two options: With no other arguments, it will
* return nil;if the optional code block is
* specified, then that will be run and its result returned.
*
* h = { "a" => { "b" => { "c" => 100 } } }
* h.traverse("a", "b", "c") #=> 100
* h.traverse("a", "z") #=> nil
* h.traverse("a", "z") { |key| "#{key} not found"} #=> "z not found"
*/
static VALUE
rb_hash_traverse(int argc, VALUE *argv, VALUE hash)
{
VALUE required;
VALUE rval = hash;
int i;
rb_scan_args(argc, argv, "1*", &required, &argv);
rb_ary_unshift(argv, required);
for (i = 0; i < RARRAY_LEN(argv) ; i++) {
rval = rb_hash_aref(rval, RARRAY_PTR(argv)[i]);
if (!rb_obj_is_kind_of(rval, rb_cHash)){
if (i < RARRAY_LEN(argv) - 1){
rval = Qnil;
}
break;
}
}
if (rval == Qnil && rb_block_given_p()){
rval = rb_yield(RARRAY_PTR(argv)[i]);
}
return rval;
}
/*
* call-seq:
* hsh.default(key=nil) -> obj
*
* Returns the default value, the value that would be returned by
......
rb_define_method(rb_cHash,"hash", rb_hash_hash, 0);
rb_define_method(rb_cHash,"eql?", rb_hash_eql, 1);
rb_define_method(rb_cHash,"fetch", rb_hash_fetch_m, -1);
rb_define_method(rb_cHash,"traverse", rb_hash_traverse, -1);
rb_define_method(rb_cHash,"[]=", rb_hash_aset, 2);
rb_define_method(rb_cHash,"store", rb_hash_aset, 2);
rb_define_method(rb_cHash,"default", rb_hash_default, -1);
test/ruby/test_hash.rb
end
end
def test_traverse
hash = { :l1 => { :l2 => { :l3 => 100 } } }
assert_raise(ArgumentError) { hash.traverse }
assert_nothing_raised { hash.traverse 'gumby' }
assert_equal(nil, hash.traverse('nonexistent'))
assert_equal({ :l2 => { :l3 => 100 } }, hash.traverse(:l1))
assert_equal('gumbygumby', hash.traverse('gumby') {|k| k * 2 })
assert_equal(100, hash.traverse(:l1, :l2, :l3))
assert_equal(nil, hash.traverse(:l1, :l2, :l3, :l4))
end
class TestSubHash < TestHash
class SubHash < Hash
end
    (1-1/1)