https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112016-04-14T06:56:09ZRuby Issue Tracking SystemRuby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=580752016-04-14T06:56:09Zsawa (Tsuyoshi Sawada)
<ul></ul><p>This makes sense only within limited cases, i.e. when the same key never appears at different depths. For example, if you get an error:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">hash</span><span class="p">.</span><span class="nf">dig!</span><span class="p">(</span><span class="ss">:foo</span><span class="p">,</span> <span class="ss">:bar</span><span class="p">,</span> <span class="ss">:foo</span><span class="p">)</span> <span class="c1"># => KeyError: Key not found: :foo</span>
</code></pre>
<p>you cannot tell whether the <code>:foo</code> at the first depth or the third depth (or both) is missing. In such case, there is not much difference from doing:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">hash</span><span class="p">[</span><span class="ss">:foo</span><span class="p">][</span><span class="ss">:bar</span><span class="p">][</span><span class="ss">:foo</span><span class="p">]</span> <span class="c1"># => NoMethodError: undefined method `[]' for nil:NilClass</span>
</code></pre>
<p>from the point of view of information the error provides. (With <code>dig!</code>, all you can tell is that the error was not caused by <code>:bar</code>.) I do not see much value in having a method for such limited use case.</p> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=580762016-04-14T07:21:28Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/58076/diff?detail_id=40892">diff</a>)</li></ul><p>I'm negative because:</p>
<ol>
<li>
<p>This example is wrong.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">places</span><span class="p">.</span><span class="nf">dig</span> <span class="ss">:countries</span><span class="p">,</span> <span class="ss">:canada</span><span class="p">,</span> <span class="ss">:ontario</span> <span class="c1"># => nil</span>
</code></pre>
<p>It raises a <code>TypeError</code>.</p>
</li>
<li>
<p>It feels curious to me that the method with '!' raises an exception whereas the method without '!' doesn't.</p>
</li>
</ol> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=580772016-04-14T07:22:28Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>Nobuyoshi Nakada wrote:</p>
<blockquote>
<p>It raises a <code>TypeError</code>.</p>
</blockquote>
<p>So you have the method which raises an exception already.</p> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=580782016-04-14T08:09:37Zsawa (Tsuyoshi Sawada)
<ul></ul><p>Nobuyoshi Nakada wrote:</p>
<blockquote>
<p>It raises a <code>TypeError</code>.</p>
</blockquote>
<p>I think it is a typographical error of</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">places</span><span class="p">.</span><span class="nf">dig</span> <span class="ss">:countries</span><span class="p">,</span> <span class="ss">:ontario</span> <span class="c1"># => nil</span>
<span class="n">places</span><span class="p">.</span><span class="nf">dig!</span> <span class="ss">:countries</span><span class="p">,</span> <span class="ss">:ontario</span> <span class="c1"># => KeyError: Key not found: :ontario</span>
</code></pre> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=580852016-04-15T03:03:45Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<ul></ul><p>I don't like the name. It doesn't uniform other usage of bang in method names.</p> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=581052016-04-16T04:20:00Zshevegen (Robert A. Heiler)shevegen@gmail.com
<ul></ul><p>I concur with Shyouhei Urabe - the name seems to not entirely fit the<br>
given outcome.</p>
<p>More typical use cases of methods with ! bang, if we ignore any<br>
exception, would be more akin to things such as:</p>
<pre><code>x = "abc" # => "abc"
x.delete 'c' # => "ab"
x # => "abc"
x.delete! 'c' # => "ab"
x # => "ab"
</code></pre>
<p>On the topic of hashes as data structures, assumingly that they<br>
may be more nested than the usual array, I tend to always attempt<br>
to have all hashes and arrays as simple as possible, if and when<br>
that is possible (it is not always possible, see the older<br>
discussions about before .dig was added; but dig! is a weird name,<br>
we want to obtain something, not change the data structure right?).</p> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=661882017-08-15T18:35:29Zk0kubun (Takashi Kokubun)takashikkbn@gmail.com
<ul></ul><p>How about this name?</p>
<pre><code>places.deep_fetch(:countries, :canada, :ontario)
</code></pre>
<p>I've encountered the case which I did "places.fetch(:countries).fetch(:canada).fetch(:ontario)" multiple times. I want this method.</p> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=759392018-12-28T05:15:51Zrobb (Robb Shecter)robb+ruby@weblaws.org
<ul></ul><p>Thanks everyone, for the discussion. I realize that my original comparison with #dig had a typographical error. Here's a gem implementation, with examples that are correct: <a href="https://github.com/dogweather/digbang" class="external">https://github.com/dogweather/digbang</a></p>
<pre><code>require 'dig_bang'
places = {
world: {
uk: true,
usa: true
}
}
# No difference when the key exists
places.dig :world, :uk # true
places.dig! :world, :uk # true
# A relevant error when the key is missing
places.dig :world, :uk, :alaska # nil
places.dig! :world, :uk, :alaska # KeyError: Key not found: :alaska
</code></pre>
<p>About the method name with the bang. I see that this might be more of a Rails naming convention, which <code>!</code> methods perform the same action, but throw an error instead of returning a <code>nil</code> on failure. And that's exactly my intent with <code>dig!</code> vs. <code>dig</code>. Basically, a "checked" dig. I don't think that Ruby has a naming convention for an alternate interface which throws an exception vs. return a nil. (?)</p>
<pre><code>module DigBang
def self.fetch_all(fetchable, keys)
keys.reduce(fetchable) { |a, e| a.fetch(e) }
end
end
class Hash
def dig!(*keys)
DigBang.fetch_all(self, keys)
end
end
class Array
def dig!(*keys)
DigBang.fetch_all(self, keys)
end
end
</code></pre> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=759402018-12-28T05:31:36Zrobb (Robb Shecter)robb+ruby@weblaws.org
<ul></ul><p>Another naming idea is <code>#fetch_all</code>, signalling that this is essentially a <code>#fetch</code> over a list of keys.</p> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=765352019-01-26T14:18:46Zk0kubun (Takashi Kokubun)takashikkbn@gmail.com
<ul><li><strong>Has duplicate</strong> <i><a class="issue tracker-2 status-1 priority-4 priority-default" href="/issues/15563">Feature #15563</a>: #dig that throws an exception if a key doesn't exist</i> added</li></ul> Ruby master - Feature #12282: Hash#dig! for repeated applications of Hash#fetchhttps://bugs.ruby-lang.org/issues/12282?journal_id=784802019-06-12T12:46:37Zk0kubun (Takashi Kokubun)takashikkbn@gmail.com
<ul><li><strong>Has duplicate</strong> <i><a class="issue tracker-2 status-1 priority-4 priority-default" href="/issues/14602">Feature #14602</a>: Version of dig that raises error if a key is not present</i> added</li></ul>