[ruby-core:95876] [Ruby master Feature#15563] #dig that throws an exception if an key doesn't exist

[email protected]
Newsgroups gmane.comp.lang.ruby.core
Message-ID <redmine.journal-82713.20191118130830.562eb2d3d9d692f5@ruby-lang.org>
Issue #15563 has been updated by 3limin4t0r (Johan Wentholt).

Description updated

Changed naming from `#dig_e` to `#traverse`. Removed alternative options, and kept the strict version since `#fetch` is also strict. Possibility to expand upon this with a block or `:default` keyword argument is possible, but should be its own feature request.

----------------------------------------
Feature #15563: #dig that throws an exception if an key doesn't exist
https://bugs.ruby-lang.org/issues/15563#change-82713

* Author: 3limin4t0r (Johan Wentholt)
* Status: Open
* Priority: Normal
* Assignee: 
* Target version: 
----------------------------------------
Ruby 2.3.0 introduced `#dig` for *Array*, *Hash* and *Struct*. Both *Array* and *Hash* have `#fetch` which does the same as `#[]`, but instead of returning the default value an exception is raised (unless a second argument or block is given). *Hash* also has `#fetch_values` which does the same as `#values_at`, raising an exception if an key is missing. For `#dig` there is no such option.

My proposal is to add a method which does the same as `#dig`, but instead of using the `#[]` accessor it uses `#fetch`.

This method would look something like this:

```Ruby
module Traversable
  def traverse(key, *others)
    value = fetch(key)
    return value if others.empty?

    if value.respond_to?(__method__, true)
      value.send(__method__, *others)
    else
      raise TypeError, "#{value.class} does not have ##{__method__} method"
    end
  end
end

Array.include(Traversable)
Hash.include(Traversable)
```

The exception raised is taken from `#dig` (`[1].dig(0, 1) #=> TypeError: Integer does not have #dig method`).

```Ruby
yaml = YAML.load_file('some_file.yml')

# this change is meant to make chaining #fetch calls more easy
yaml.fetch('foo').fetch('bar').fetch('baz')

# would be replaced with
yaml.traverse('foo', 'bar', 'baz')
```

I'm curious to hear what you guys think about the idea as a whole, the method name and the two points described above.
 



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

Unsubscribe: <mailto:[email protected]?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.