Ruby Issue Tracking System: Issueshttps://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112020-07-17T04:00:20ZRuby Issue Tracking System
Redmine Ruby master - Bug #17034 (Closed): Unexpected behavior in #max for beginless rangehttps://redmine.ruby-lang.org/issues/170342020-07-17T04:00:20Zcitizen428 (Michael Kohl)citizen428@gmail.com
<p>When calling <code>max</code> on a beginless range, a non-intuitive error gets raised:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">r</span> <span class="o">=</span> <span class="o">..</span><span class="mi">9</span>
<span class="n">r</span><span class="p">.</span><span class="nf">max</span>
<span class="c1"># ArgumentError: comparison of NilClass with 9 failed</span>
</code></pre>
<p>There's a check for <code>NIL_P(RANGE_BEG(range))</code> but it's inside another check which is false for the example case above:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">if</span> <span class="p">(</span><span class="n">rb_block_given_p</span><span class="p">()</span> <span class="o">||</span> <span class="p">(</span><span class="no">EXCL</span><span class="p">(</span><span class="n">range</span><span class="p">)</span> <span class="o">&&</span> <span class="o">!</span><span class="n">nm</span><span class="p">)</span> <span class="o">||</span> <span class="n">argc</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="no">NIL_P</span><span class="p">(</span><span class="no">RANGE_BEG</span><span class="p">(</span><span class="n">range</span><span class="p">)))</span> <span class="p">{</span>
<span class="n">rb_raise</span><span class="p">(</span><span class="n">rb_eRangeError</span><span class="p">,</span> <span class="s2">"cannot get the maximum of beginless range with custom comparison method"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">rb_call_super</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">);</span>
<span class="p">}</span>
</code></pre>
<p>The first part of the condition is false since there is no block, and even though I'm not sure what <code>EXCL</code> does the second part of the condition will be false due to <code>!nm</code> (<code>nm</code> will be true because of <code>FIXNUM_P(e)</code>). So I think the error gets raised here:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">int</span> <span class="n">c</span> <span class="o">=</span> <span class="no">OPTIMIZED_CMP</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">e</span><span class="p">,</span> <span class="n">cmp_opt</span><span class="p">);</span>
</code></pre>
<p>I think this is not ideal. Possible solutions:</p>
<ol>
<li>Return <code>e</code> (<code>RANGE_END(range)</code> for beginless ranges or</li>
<li>return a <code>RangeError</code> with a message like "cannot get the maximum of beginless range" (similar to <code>.min</code>).</li>
</ol>
<p>Happy to provide a patch if people want this changed and can agree on what the new behavior should be.</p> Ruby master - Feature #9807 (Open): String.new with blockhttps://redmine.ruby-lang.org/issues/98072014-05-06T11:22:07Zcitizen428 (Michael Kohl)citizen428@gmail.com
<p>After a discussion in our team chat today, I wondered if it would be a good idea to have a version of String.new that accepts a block and works as a string builder. Something like</p>
<pre><code>string = String.new("foo") do |s|
s << "bar"
end
string #=> "foobar"
</code></pre>
<p>If the argument is omitted an empty string would be passed to the block instead.</p>
<p>That could be a nice solution to avoid all the Array#join and "".tap hacks for string creation.</p> Ruby master - Feature #6847 (Rejected): Hash#extracthttps://redmine.ruby-lang.org/issues/68472012-08-10T02:01:48Zcitizen428 (Michael Kohl)citizen428@gmail.com
<p>I often need a method to extract "subhashes" from hashes. I often monkey-patched this into hash and found "extract" to be a good name for the method. Afterwards I found out that there actually is a mutating method called "extract!" in ActiveSupport, so I guess the name is kinda established. Here's the Ruby version from my private extension library, if there's any interest in this I would try to re-implement it in C:</p>
<p>class Hash<br>
def extract(*ks)<br>
existing = keys & ks<br>
Hash[existing.zip(values_at(*existing))]<br>
end<br>
end</p> Ruby master - Feature #6817 (Open): Partial applicationhttps://redmine.ruby-lang.org/issues/68172012-07-31T15:38:35Zcitizen428 (Michael Kohl)citizen428@gmail.com
<p>I know that what I propose here is a significant change to Ruby, but it's part of my ongoing quest to get some more functional programming features into Ruby (see also <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: Array#zip_with (Assigned)" href="https://redmine.ruby-lang.org/issues/4539">#4539</a> and <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: public #self (Closed)" href="https://redmine.ruby-lang.org/issues/6373">#6373</a>).</p>
<p>I was wondering if it would make sense to maybe introduce partial application to Ruby? So that instead of</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">).</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="p">}</span>
</code></pre>
<p>or the somewhat unwieldy</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">).</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="mi">2</span><span class="p">.</span><span class="nf">method</span><span class="p">(:</span><span class="o">+</span><span class="p">))</span>
</code></pre>
<p>one could just write</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">).</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="mi">2</span><span class="p">.</span><span class="nf">+</span><span class="p">)</span>
</code></pre>
<p>which I think has a quite rubyish feel to it. I have a POC implementation in Ruby (I tried it with various <code>Fixnum</code> methods) over at <a href="http://citizen428.net/blog/2012/07/30/ruby-left-section-for-infix-operators" class="external">my blog</a>, but that was just a quick hack and obviously I don't want to monkey-patch every method with arity 1, but it was a nice way of exploring possible syntax.</p> Ruby master - Feature #4539 (Assigned): Array#zip_withhttps://redmine.ruby-lang.org/issues/45392011-03-30T06:21:32Zcitizen428 (Michael Kohl)citizen428@gmail.com
<p>Inspired by Haskell's <code>zipWith</code> function, I hacked on together for Ruby:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><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="nf">zip_with</span><span class="p">([</span><span class="mi">6</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="p">:</span><span class="o">+</span><span class="p">)</span> <span class="c1">#=> [7, 7, 7]</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="nf">zip_with</span><span class="p">([</span><span class="mi">6</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">])</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="o">|</span> <span class="mi">3</span><span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="n">b</span> <span class="p">}</span> <span class="c1">#=> [15, 16, 17]</span>
</code></pre>
<p>So far I only have a Ruby version of it:</p>
<p><a href="https://gist.github.com/731702b90757e21cadcb" class="external">https://gist.github.com/731702b90757e21cadcb</a></p>
<p>My questions:</p>
<ol>
<li>
<p>Would this method be considered a worthwhile addition to <code>Array</code>?</p>
</li>
<li>
<p>I've never hacked on the C side of Ruby (read some parts of the source though) and my C is quite rusty. I'd like to change that, would somebody be willing to help me turn this into a proper patch?</p>
</li>
</ol>