From: walerian.sobczak@gmail.com
To: ruby-core@ruby-lang.org
Subject: [ruby-core:91795] [Ruby trunk Feature#15563] #dig that throws an exception if an key doesn't exist
Date: Tue, 12 Mar 2019 21:56:02 +0000 (UTC) [thread overview]
Message-ID: <redmine.journal-77069.20190312215601.1f4d2a6855b0892a@ruby-lang.org> (raw)
In-Reply-To: redmine.issue-15563.20190125170732@ruby-lang.org
Issue #15563 has been updated by walerian (Walerian Sobczak).
I would suggest `#retrieve`. It's just a **stronger** `#fetch`, and the dictionary definition reflects its meaning:
> retrieve (verb)
> 1. get or bring (something) back from somewhere
> 2. find or extract
The name is still short and simple, but also idiomatic and meaningful at the same time.
``` ruby
config = YAML.load_file('config.yml')
# so instead of this:
config.fetch('production').fetch('environment').fetch('SECRET_KEY_BASE')
# we would have:
config.retrieve('production', 'environment', 'SECRET_KEY_BASE')
```
----------------------------------------
Feature #15563: #dig that throws an exception if an key doesn't exist
https://bugs.ruby-lang.org/issues/15563#change-77069
* 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 DigWithException
def dig_e(key, *others)
value = fetch(key)
return value if value.nil? || 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(DigWithException)
Hash.include(DigWithException)
```
The exception raised is also taken from `#dig` (`[1].dig(0, 1) #=> TypeError: Integer does not have #dig method`). I personally have my issues with the name `#dig_e`, but I haven't found a better name yet.
There are also a few other things that I haven't thought out yet.
1. Should this method be able to accept a block which, will be passed to the `#fetch` call and recursive `#dig_e` calls?
```Ruby
module DigWithException
def dig_e(key, *others, &block)
value = fetch(key, &block)
return value if value.nil? || others.empty?
if value.respond_to?(__method__, true)
value.send(__method__, *others, &block)
else
raise TypeError, "#{value.class} does not have ##{__method__} method"
end
end
end
Array.include(DigWithException)
Hash.include(DigWithException)
```
2. I currently kept the code compatible with the `#dig` description.
> Extracts the nested value specified by the sequence of *key* objects by calling `dig` at each step, returning `nil` if any intermediate step is `nil`.
However, with this new version of the method one could consider dropping the *"returning `nil` if any intermediate step is `nil`"* part, since this would be the more strict version.
```Ruby
module DigWithException
def dig_e(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(DigWithException)
Hash.include(DigWithException)
```
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/
next prev parent reply other threads:[~2019-03-12 21:56 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <redmine.issue-15563.20190125170732@ruby-lang.org>
2019-01-25 17:07 ` [ruby-core:91265] [Ruby trunk Feature#15563] #dig that throws an exception if an key doesn't exist djo.went
2019-01-25 17:48 ` [ruby-core:91266] " djo.went
2019-01-25 19:35 ` [ruby-core:91267] " shevegen
2019-01-26 13:14 ` [ruby-core:91284] " Ruby-Lang
2019-01-26 13:54 ` [ruby-core:91285] " matz
2019-01-26 14:35 ` [ruby-core:91286] " takashikkbn
2019-01-28 17:06 ` [ruby-core:91308] " djo.went
2019-03-12 21:56 ` walerian.sobczak [this message]
2019-06-13 8:08 ` [ruby-core:93096] " knu
2019-11-18 13:08 ` [ruby-core:95876] [Ruby master " djo.went
2019-11-18 13:16 ` [ruby-core:95877] " djo.went
2019-12-01 8:43 ` [ruby-core:96044] " ariel.caplan
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.ruby-lang.org/en/community/mailing-lists/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=redmine.journal-77069.20190312215601.1f4d2a6855b0892a@ruby-lang.org \
--to=ruby-core@ruby-lang.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).