https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112019-05-06T06:01:09ZRuby Issue Tracking SystemRuby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=779292019-05-06T06:01:09Zshevegen (Robert A. Heiler)shevegen@gmail.com
<ul></ul><p>What is the difference towards e. g. <code>hash.delete()</code>?</p>
<p>People may ask about this difference. The '!'<br>
too since you can use e. g. <code>Hash #delete</code> as-is.</p>
<p>Also without '!', I am not sure if extract is a good<br>
name per se, but these are just random comments mostly,<br>
you only have to convince matz, not me. :)</p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=779962019-05-13T23:21:09Zbogdanvlviv (Bogdan Denkovych)
<ul><li><strong>Subject</strong> changed from <i>Add `Array#extract!`, `Hash#extract!`, and `ENV::extract!`</i> to <i>Add `Array#extract`, `Hash#extract`, and `ENV::extract`</i></li><li><strong>Description</strong> updated (<a title="View differences" href="/journals/77996/diff?detail_id=51790">diff</a>)</li></ul> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=780002019-05-14T00:33:25Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>Why <code>Array#extract</code> has no argument but takes a block, while <code>Hash</code> and <code>ENV</code> are opposite?</p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=780112019-05-14T21:24:06Zbogdanvlviv (Bogdan Denkovych)
<ul></ul><p>nobu (Nobuyoshi Nakada) wrote:</p>
<blockquote>
<p>Why <code>Array#extract</code> has no argument but takes a block, while <code>Hash</code> and <code>ENV</code> are opposite?</p>
</blockquote>
<p>I implemented those methods to mirror similar behavior as it is in Active Support, but I also feel like we need to discuss more about behavior and signature of those methods:</p>
<h2>About <code>Array#extract</code>
</h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">numbers</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">]</span>
<span class="n">odd_numbers</span> <span class="o">=</span> <span class="n">numbers</span><span class="p">.</span><span class="nf">extract</span> <span class="p">{</span> <span class="o">|</span><span class="n">number</span><span class="o">|</span> <span class="n">number</span><span class="p">.</span><span class="nf">odd?</span> <span class="p">}</span> <span class="c1"># => [1, 3, 5, 7, 9]</span>
<span class="n">numbers</span> <span class="c1"># => [0, 2, 4, 6, 8]</span>
</code></pre>
<p>I do believe that this method should mirror the behavior and the method signature of <code>Array#reject!</code> <a href="https://docs.ruby-lang.org/en/2.6.0/Array.html#method-i-reject-21" class="external">https://docs.ruby-lang.org/en/2.6.0/Array.html#method-i-reject-21</a> since they are similar except one thing - <code>Array#extract</code> returns elements for which the block returns a <code>true</code> value. Actually "return elements for the block returns a <code>true</code> value" is the main reason why I would like to add this method because there could be and <a href="https://bogdanvlviv.com/posts/ruby/rails/array-extract-to-activesupport-6-0.html" class="external">there already are lots of use cases for those methods</a>. So I believe this method good as it is.</p>
<h2>About <code>Hash#extract</code> and <code>ENV::extract</code>
</h2>
<p>First of all, thank you for your question. I also feel <code>Hash#extract</code>/<code>ENV::extract</code> should receive a block, in other words should mirror the behavior and the method signature o<code>Hash#reject!</code>, but return the hash with key/value pairs for which the block returns <code>true</code>. There is an example to make it clear:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">h</span> <span class="o">=</span> <span class="p">{</span><span class="ss">a: </span><span class="mi">100</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">200</span><span class="p">,</span> <span class="ss">c: </span><span class="mi">300</span><span class="p">}</span>
<span class="n">h</span><span class="p">.</span><span class="nf">extract</span> <span class="p">{</span><span class="o">|</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="n">v</span> <span class="o">></span> <span class="mi">150</span><span class="p">}</span> <span class="c1"># => {:b=>200, :c=>300}</span>
<span class="n">h</span> <span class="c1"># => {:a=>100}</span>
</code></pre>
<p>I also feel like we should add <code>Hash#slice!</code>(since we have <code>Hash#slice</code>) that would behave exactly in the way I proposed to <code>Hash#extract</code> initially.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">h</span> <span class="o">=</span> <span class="p">{</span><span class="ss">a: </span><span class="mi">100</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">200</span><span class="p">,</span> <span class="ss">c: </span><span class="mi">300</span><span class="p">}</span>
<span class="n">h</span><span class="p">.</span><span class="nf">slice!</span><span class="p">(</span><span class="ss">:a</span><span class="p">)</span> <span class="c1"># => {:a=>100}</span>
<span class="n">h</span> <span class="c1"># => {:b=>200, :c=>300}</span>
<span class="n">h</span><span class="p">.</span><span class="nf">slice!</span><span class="p">(</span><span class="ss">:b</span><span class="p">,</span> <span class="ss">:c</span><span class="p">,</span> <span class="ss">:d</span><span class="p">)</span> <span class="c1"># => {:b=>200, :c=>300}</span>
<span class="n">h</span> <span class="c1"># => {}</span>
</code></pre>
<p>I would like to work on <code>Hash#slice!</code> implementation as well.</p>
<p>Let me know what you think about it.</p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=780682019-05-18T14:45:57Zbogdanvlviv (Bogdan Denkovych)
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/78068/diff?detail_id=51825">diff</a>)</li></ul><p>I just changed the implementation of <code>Hash#extract</code> and <code>ENV::extract</code> as it's described in the previous note <a href="https://bugs.ruby-lang.org/issues/15831#note-4" class="external">https://bugs.ruby-lang.org/issues/15831#note-4</a></p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=780792019-05-19T12:25:57Zbogdanvlviv (Bogdan Denkovych)
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/78079/diff?detail_id=51831">diff</a>)</li></ul> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=780802019-05-19T15:51:29Zbogdanvlviv (Bogdan Denkovych)
<ul><li><strong>Subject</strong> changed from <i>Add `Array#extract`, `Hash#extract`, and `ENV::extract`</i> to <i>Add `Array#extract`, `Hash#extract`, and `ENV.extract`</i></li><li><strong>Description</strong> updated (<a title="View differences" href="/journals/78080/diff?detail_id=51833">diff</a>)</li></ul> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=781372019-05-22T07:45:39Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Rejected</i></li></ul><p>I don't think we have seen the use-case that this method is absolutely necessary. I also concern about the name conflict with the ActiveSupport method.</p>
<p>Let me see the real-world use-case, please.</p>
<p>Matz.</p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=781452019-05-22T09:52:06Zbogdanvlviv (Bogdan Denkovych)
<ul></ul><p>matz (Yukihiro Matsumoto) wrote:</p>
<blockquote>
<p>I don't think we have seen the use-case that this method is absolutely necessary. I also concern about the name conflict with the ActiveSupport method.</p>
<p>Let me see the real-world use-case, please.</p>
<p>Matz.</p>
</blockquote>
<p>There are use-cases of <code>Array#extract</code> in this Pull Request <a href="https://github.com/rails/rails/pull/33137/files" class="external">https://github.com/rails/rails/pull/33137/files</a></p>
<p>There are also use-cases where <code>Array#extract</code> would fit in the ruby/ruby codebase:</p>
<ol>
<li><a href="https://github.com/ruby/ruby/blob/d0a54673202458455244f79ed212a97727f0c7c7/lib/rubygems/uninstaller.rb#L91-L93" class="external">https://github.com/ruby/ruby/blob/d0a54673202458455244f79ed212a97727f0c7c7/lib/rubygems/uninstaller.rb#L91-L93</a></li>
</ol>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">- default_specs, list = list.partition do |spec|
- spec.default_gem?
- end
</span><span class="gi">+ default_specs = list.extract {|spec| spec.default_gem?}
</span></code></pre>
<ol start="2">
<li><a href="https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/lib/rubygems/commands/cleanup_command.rb#L128-L130" class="external">https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/lib/rubygems/commands/cleanup_command.rb#L128-L130</a></li>
</ol>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">- default_gems, gems_to_cleanup = gems_to_cleanup.partition do |spec|
- spec.default_gem?
- end
</span><span class="gi">+ default_gems = gems_to_cleanup.extract {|spec| spec.default_gem?}
</span></code></pre>
<ol start="3">
<li><a href="https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/spec/mspec/lib/mspec/runner/context.rb#L185-L187" class="external">https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/spec/mspec/lib/mspec/runner/context.rb#L185-L187</a></li>
</ol>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">- filtered, @examples = @examples.partition do |ex|
- ex.filtered?
- end
</span><span class="gi">+ filtered = @examples.extract {|ex| ex.filtered? }
</span></code></pre>
<ol start="4">
<li><a href="https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/lib/rubygems/dependency.rb#L331" class="external">https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/lib/rubygems/dependency.rb#L331</a></li>
</ol>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">- pre, matches = matches.partition { |spec| spec.version.prerelease? }
</span><span class="gi">+ pre = matches.extract { |spec| spec.version.prerelease? }
</span></code></pre>
<ol start="5">
<li><a href="https://github.com/ruby/ruby/blob/2e8b9aba9bef6c913e5b2de25b24026943438519/lib/bundler/resolver.rb#L118" class="external">https://github.com/ruby/ruby/blob/2e8b9aba9bef6c913e5b2de25b24026943438519/lib/bundler/resolver.rb#L118</a></li>
</ol>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">- pre, results = results.partition {|spec| spec.version.prerelease? }
</span><span class="gi">+ pre = results.extract {|spec| spec.version.prerelease? }
</span></code></pre>
<ol start="6">
<li><a href="https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/test/lib/test/unit.rb#L507" class="external">https://github.com/ruby/ruby/blob/d48783bb0236db505fe1205d1d9822309de53a36/test/lib/test/unit.rb#L507</a></li>
</ol>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">- suites, rep = rep.partition {|r| r[:testcase] && r[:file] && r[:report].any? {|e| !e[2].is_a?(MiniTest::Skip)}}
</span><span class="gi">+ suites = rep.extract {|r| r[:testcase] && r[:file] && r[:report].any? {|e| !e[2].is_a?(MiniTest::Skip)}}
</span></code></pre>
<p>By the way, <a href="https://github.com/numpy/numpy" class="external">numpy/numpy</a> library has similar <code>extract</code> method: <a href="https://www.numpy.org/devdocs/reference/generated/numpy.extract.html?highlight=extract" class="external">https://www.numpy.org/devdocs/reference/generated/numpy.extract.html?highlight=extract</a></p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=781932019-05-24T10:39:53Zbogdanvlviv (Bogdan Denkovych)
<ul></ul><blockquote>
<p>I also concern about the name conflict with the ActiveSupport method.</p>
</blockquote>
<p>I guess this comment addressed <a href="https://bugs.ruby-lang.org/issues/15863" class="external">https://bugs.ruby-lang.org/issues/15863</a> that adds <code>Hash#slice!</code>, right?<br>
Active Support doesn't have any <code>extract</code> methods, only <code>extract!</code>(with bang).</p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=877442020-09-26T11:18:16Zbogdanvlviv (Bogdan Denkovych)
<ul></ul><p>I'm wondering to know whether use-cases, mentioned in <a href="https://bugs.ruby-lang.org/issues/15831#note-9" class="external">https://bugs.ruby-lang.org/issues/15831#note-9</a>, are good enough to reconsider the decision to add these methods to Ruby?</p> Ruby master - Feature #15831: Add `Array#extract`, `Hash#extract`, and `ENV.extract`https://bugs.ruby-lang.org/issues/15831?journal_id=877562020-09-27T07:52:32Zduerst (Martin Dürst)duerst@it.aoyama.ac.jp
<ul></ul><p>I'm not exactly at ease with the fact that the proposed methods both change the receiver and return a result. But if the names have an '!' at the end, it might be okay.</p>