Issue #11762 has been updated by Marc-Andre Lafortune.

Assignee set to Yukihiro Matsumoto

I feel that either `dig` should be safe only against `nil` somewhere in the digging path (a bit like `&.`), or it's should always safe, even when digging through unexpected objects or indices.

Currently:

    {a: 'hello'}.dig(:a, :b) # => nil
    {a: []}.dig(:a, :b) # => TypeError

I believe they should either both raise an error, or both return `nil`.

I'm unsure as to the best solution. I'd guess, like Colin, that returning `nil` is probably the best. Makes debugging harder when writing new code, but makes backward compatibility easier, since old code using `dig` wouldn't bomb if the data layout changes in the future.

Matz, what do you think about this?


diff --git a/object.c b/object.c
index ff2db0b..c863fbe 100644
--- a/object.c
+++ b/object.c
@@ -3184,7 +3184,12 @@ rb_obj_dig(int argc, VALUE *argv, VALUE obj, VALUE notfound)
                break;
              case T_ARRAY:
                if (dig_basic_p(obj, &ary)) {
-                   obj = rb_ary_at(obj, *argv);
+                   VALUE index = rb_check_to_int(*argv);
+                   if (NIL_P(index)) {
+                       obj = Qnil;
+                   } else {
+                       obj = rb_ary_at(obj, index);
+                   }
                    continue;
                }
                break;
diff --git a/test/ruby/test_array.rb b/test/ruby/test_array.rb
index 0922cb4..b117a7e 100644
--- a/test/ruby/test_array.rb
+++ b/test/ruby/test_array.rb
@@ -2655,6 +2655,7 @@ def test_dig
     h = @cls[@cls[{a: 1}], 0]
     assert_equal(1, h.dig(0, 0, :a))
     assert_nil(h.dig(1, 0))
+    assert_nil(h.dig(0, :foo))
   end
 
   private


----------------------------------------
Bug #11762: Array#dig can raise TypeError: no implicit conversion of Symbol/String into Integer
https://bugs.ruby-lang.org/issues/11762#change-55257

* Author: Colin Kelley
* Status: Open
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* ruby -v: 2.3.0-preview1
* Backport: 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN
----------------------------------------
If you try to `dig` in an Array using a symbol or string, a `TypeError` exception will be raised:

irb> ['zero', 'one', 'two'].dig(:first)
TypeError: no implicit conversion of Symbol into Integer
    from (irb):1:in `dig'
    from (irb):1

I think it should return `nil` in this case.  The most typical use case for `dig` is to dig through parsed JSON and either find the result we expected or else `nil`.  Wouldn't it defeat the purpose of `dig` if we had to wrap calls to it in a `rescue` to handle the case that an Array was present where we expected a Hash?

Can we clarify the desired behavior for this case, then update the documentation and tests to reflect that?



-- 
https://bugs.ruby-lang.org/