dig
* array.c (rb_ary_dig): new method Array#dig. * hash.c (rb_hash_dig): new method Hash#dig. * object.c (rb_obj_dig): dig in nested arrays/hashes. [Feature #11643] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@52504 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
50dbcf5f6d
commit
29862685c0
@ -1,3 +1,12 @@
|
|||||||
|
Mon Nov 9 21:27:23 2015 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* array.c (rb_ary_dig): new method Array#dig.
|
||||||
|
|
||||||
|
* hash.c (rb_hash_dig): new method Hash#dig.
|
||||||
|
|
||||||
|
* object.c (rb_obj_dig): dig in nested arrays/hashes.
|
||||||
|
[Feature #11643]
|
||||||
|
|
||||||
Mon Nov 9 18:00:47 2015 Yuki Nishijima <mail@yukinishijima.net>
|
Mon Nov 9 18:00:47 2015 Yuki Nishijima <mail@yukinishijima.net>
|
||||||
|
|
||||||
* gems/bundled_gems: Upgrade the did_you_mean gem to 1.0.0.beta3
|
* gems/bundled_gems: Upgrade the did_you_mean gem to 1.0.0.beta3
|
||||||
|
2
NEWS
2
NEWS
@ -42,6 +42,7 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
* Array
|
* Array
|
||||||
|
|
||||||
* Array#bsearch_index [Feature #10730]
|
* Array#bsearch_index [Feature #10730]
|
||||||
|
* Array#dig [Feature #11643]
|
||||||
|
|
||||||
* Enumerable
|
* Enumerable
|
||||||
|
|
||||||
@ -57,6 +58,7 @@ with all sufficient information, see the ChangeLog file.
|
|||||||
* Hash
|
* Hash
|
||||||
|
|
||||||
* Hash#fetch_values [Feature #10017]
|
* Hash#fetch_values [Feature #10017]
|
||||||
|
* Hash#dig [Feature #11643]
|
||||||
|
|
||||||
* IO
|
* IO
|
||||||
|
|
||||||
|
26
array.c
26
array.c
@ -1302,7 +1302,7 @@ rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
|
|||||||
* a.at(-1) #=> "e"
|
* a.at(-1) #=> "e"
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static VALUE
|
VALUE
|
||||||
rb_ary_at(VALUE ary, VALUE pos)
|
rb_ary_at(VALUE ary, VALUE pos)
|
||||||
{
|
{
|
||||||
return rb_ary_entry(ary, NUM2LONG(pos));
|
return rb_ary_entry(ary, NUM2LONG(pos));
|
||||||
@ -5531,6 +5531,29 @@ rb_ary_any_p(VALUE ary)
|
|||||||
return Qfalse;
|
return Qfalse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* ary.dig(idx, ...) -> object
|
||||||
|
*
|
||||||
|
* Retrieves the value object corresponding to the each <i>idx</i>
|
||||||
|
* objects repeatedly.
|
||||||
|
*
|
||||||
|
* a = [[1, [2, 3]]]
|
||||||
|
*
|
||||||
|
* a.dig(0, 1, 1) #=> 3
|
||||||
|
* a.dig(0, 0, 0) #=> nil
|
||||||
|
*/
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_ary_dig(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
||||||
|
self = rb_ary_at(self, *argv);
|
||||||
|
if (!--argc) return self;
|
||||||
|
++argv;
|
||||||
|
return rb_obj_dig(argc, argv, self, Qnil);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Arrays are ordered, integer-indexed collections of any object.
|
* Arrays are ordered, integer-indexed collections of any object.
|
||||||
*
|
*
|
||||||
@ -5882,6 +5905,7 @@ Init_Array(void)
|
|||||||
rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
|
rb_define_method(rb_cArray, "bsearch", rb_ary_bsearch, 0);
|
||||||
rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
|
rb_define_method(rb_cArray, "bsearch_index", rb_ary_bsearch_index, 0);
|
||||||
rb_define_method(rb_cArray, "any?", rb_ary_any_p, 0);
|
rb_define_method(rb_cArray, "any?", rb_ary_any_p, 0);
|
||||||
|
rb_define_method(rb_cArray, "dig", rb_ary_dig, -1);
|
||||||
|
|
||||||
id_cmp = rb_intern("<=>");
|
id_cmp = rb_intern("<=>");
|
||||||
id_random = rb_intern("random");
|
id_random = rb_intern("random");
|
||||||
|
24
hash.c
24
hash.c
@ -2691,6 +2691,29 @@ rb_hash_any_p(VALUE hash)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* call-seq:
|
||||||
|
* hsh.dig(key, ...) -> object
|
||||||
|
*
|
||||||
|
* Retrieves the value object corresponding to the each <i>key</i>
|
||||||
|
* objects repeatedly.
|
||||||
|
*
|
||||||
|
* h = { foo: {bar: {baz: 1}}}
|
||||||
|
*
|
||||||
|
* h.dig(:foo, :bar, :baz) #=> 1
|
||||||
|
* h.dig(:foo, :zot) #=> nil
|
||||||
|
*/
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_hash_dig(int argc, VALUE *argv, VALUE self)
|
||||||
|
{
|
||||||
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
||||||
|
self = rb_hash_aref(self, *argv);
|
||||||
|
if (!--argc) return self;
|
||||||
|
++argv;
|
||||||
|
return rb_obj_dig(argc, argv, self, Qnil);
|
||||||
|
}
|
||||||
|
|
||||||
static int path_tainted = -1;
|
static int path_tainted = -1;
|
||||||
|
|
||||||
static char **origenviron;
|
static char **origenviron;
|
||||||
@ -4114,6 +4137,7 @@ Init_Hash(void)
|
|||||||
rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
|
rb_define_method(rb_cHash,"compare_by_identity?", rb_hash_compare_by_id_p, 0);
|
||||||
|
|
||||||
rb_define_method(rb_cHash, "any?", rb_hash_any_p, 0);
|
rb_define_method(rb_cHash, "any?", rb_hash_any_p, 0);
|
||||||
|
rb_define_method(rb_cHash, "dig", rb_hash_dig, -1);
|
||||||
|
|
||||||
/* Document-class: ENV
|
/* Document-class: ENV
|
||||||
*
|
*
|
||||||
|
@ -653,6 +653,7 @@ VALUE rb_ary_last(int, const VALUE *, VALUE);
|
|||||||
void rb_ary_set_len(VALUE, long);
|
void rb_ary_set_len(VALUE, long);
|
||||||
void rb_ary_delete_same(VALUE, VALUE);
|
void rb_ary_delete_same(VALUE, VALUE);
|
||||||
VALUE rb_ary_tmp_new_fill(long capa);
|
VALUE rb_ary_tmp_new_fill(long capa);
|
||||||
|
VALUE rb_ary_at(VALUE, VALUE);
|
||||||
size_t rb_ary_memsize(VALUE);
|
size_t rb_ary_memsize(VALUE);
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define rb_ary_new_from_args(n, ...) \
|
#define rb_ary_new_from_args(n, ...) \
|
||||||
@ -968,6 +969,7 @@ void rb_obj_copy_ivar(VALUE dest, VALUE obj);
|
|||||||
VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
|
VALUE rb_obj_equal(VALUE obj1, VALUE obj2);
|
||||||
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
|
VALUE rb_class_search_ancestor(VALUE klass, VALUE super);
|
||||||
double rb_num_to_dbl(VALUE val);
|
double rb_num_to_dbl(VALUE val);
|
||||||
|
VALUE rb_obj_dig(int argc, VALUE *argv, VALUE self, VALUE notfound);
|
||||||
|
|
||||||
struct RBasicRaw {
|
struct RBasicRaw {
|
||||||
VALUE flags;
|
VALUE flags;
|
||||||
|
47
object.c
47
object.c
@ -3144,6 +3144,52 @@ rb_f_hash(VALUE obj, VALUE arg)
|
|||||||
return rb_Hash(arg);
|
return rb_Hash(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dig_method {
|
||||||
|
VALUE klass;
|
||||||
|
int basic;
|
||||||
|
};
|
||||||
|
|
||||||
|
static ID id_dig;
|
||||||
|
|
||||||
|
static int
|
||||||
|
dig_basic_p(VALUE obj, struct dig_method *cache)
|
||||||
|
{
|
||||||
|
VALUE klass = RBASIC_CLASS(obj);
|
||||||
|
if (klass != cache->klass) {
|
||||||
|
cache->klass = klass;
|
||||||
|
cache->basic = rb_method_basic_definition_p(klass, id_dig);
|
||||||
|
}
|
||||||
|
return cache->basic;
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
|
||||||
|
{
|
||||||
|
struct dig_method hash = {Qnil}, ary = {Qnil};
|
||||||
|
|
||||||
|
for (; argc > 0; ++argv, --argc) {
|
||||||
|
if (!SPECIAL_CONST_P(obj)) {
|
||||||
|
switch (BUILTIN_TYPE(obj)) {
|
||||||
|
case T_HASH:
|
||||||
|
if (dig_basic_p(obj, &hash)) {
|
||||||
|
obj = rb_hash_aref(obj, *argv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case T_ARRAY:
|
||||||
|
if (dig_basic_p(obj, &ary)) {
|
||||||
|
obj = rb_ary_at(obj, *argv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
obj = rb_check_funcall(obj, id_dig, argc, argv);
|
||||||
|
if (obj == Qundef) return notfound;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Document-class: Class
|
* Document-class: Class
|
||||||
*
|
*
|
||||||
@ -3521,5 +3567,6 @@ void
|
|||||||
Init_Object(void)
|
Init_Object(void)
|
||||||
{
|
{
|
||||||
id_to_f = rb_intern_const("to_f");
|
id_to_f = rb_intern_const("to_f");
|
||||||
|
id_dig = rb_intern_const("dig");
|
||||||
InitVM(Object);
|
InitVM(Object);
|
||||||
}
|
}
|
||||||
|
@ -2651,6 +2651,12 @@ class TestArray < Test::Unit::TestCase
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_dig
|
||||||
|
h = @cls[@cls[{a: 1}], 0]
|
||||||
|
assert_equal(1, h.dig(0, 0, :a))
|
||||||
|
assert_nil(h.dig(1, 0))
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def need_continuation
|
def need_continuation
|
||||||
unless respond_to?(:callcc, true)
|
unless respond_to?(:callcc, true)
|
||||||
|
@ -1302,6 +1302,12 @@ class TestHash < Test::Unit::TestCase
|
|||||||
x = x
|
x = x
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_dig
|
||||||
|
h = @cls[a: @cls[b: [1, 2, 3]], c: 4]
|
||||||
|
assert_equal(1, h.dig(:a, :b, 0))
|
||||||
|
assert_nil(h.dig(:c, 1))
|
||||||
|
end
|
||||||
|
|
||||||
class TestSubHash < TestHash
|
class TestSubHash < TestHash
|
||||||
class SubHash < Hash
|
class SubHash < Hash
|
||||||
def reject(*)
|
def reject(*)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user