Issue #11762 has been updated by Colin Kelley.


As described by Matz, it sounds like the implementation would be equivalent to

~~~
def dig(key, *keys)
  value = self[key]        # may raise TypeError
  if keys.empty? || value.nil?
    value
  else
    value.respond_to?(:dig) or raise TypeError, "object does not respond to dig"
    value.dig(*keys)
  end
end
~~~

But I agree with Marc-Andre that a `NoMethodError` contract would be more natural as it removes the special case:

~~~
def dig(key, *keys)
  value = self[key]        # may raise TypeError
  if keys.empty? || value.nil?
    value
  else
    value.dig(*keys)
  end
end
~~~

That is,

~~~
hash.dig(a, b, c...)
~~~

would be exactly equivalent to

~~~
hash[a]&.[](b)&.[](c)...
~~~

However I must say I am disappointed that `dig` will raise exceptions.  Given that definition it won't be useful for digging in JSON responses whose format has not already been validated.  We can already write

~~~
hash[a][b][c] rescue nil
~~~

So is `dig` worth adding to Ruby at all, given the definition that raises exceptions?  It doesn't seem so to me.

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

* Author: Colin Kelley
* Status: Closed
* Priority: Normal
* Assignee: Yukihiro Matsumoto
* ruby -v: 2.3.0-preview2
* 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?

---Files--------------------------------
11762.patch (3.19 KB)


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