Ruby Issue Tracking System: Issues
https://redmine.ruby-lang.org/
https://redmine.ruby-lang.org/favicon.ico?1711330511
2018-12-03T03:11:38Z
Ruby Issue Tracking System
Redmine
Ruby master - Bug #15370 (Rejected): Array#=== in long running loop continually consumes more RAM
https://redmine.ruby-lang.org/issues/15370
2018-12-03T03:11:38Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>I was doing a code challenge and trying to use as few characters as possible (not shown). So instead of using <code>Array#member?</code> I tried <code>Array#===</code> and it consumed my system's RAM once I switched to that.</p>
<p>The good code here:</p>
<pre><code>freq = [0]
$<.readlines.cycle do |num|
sum = freq.last + num.to_i
break sum if freq.member? sum
freq << sum
end
</code></pre>
<p><img src="https://redmine.ruby-lang.org/attachments/download/7524/Screenshot%20from%202018-12-02%2021-33-38.png" title="Array#member?" alt="Array#member?" loading="lazy"></p>
<p>Doesn't grow or consume any extra memory… which is good.</p>
<p>But when I change it to:</p>
<pre><code>freq = [0]
$<.readlines.cycle do |num|
sum = freq.last + num.to_i
break sum if freq === sum
freq << sum
end
</code></pre>
<p>It doesn't take long to fill up 10.7 Gigs and continue consuming more RAM.</p>
<p><img src="https://redmine.ruby-lang.org/attachments/download/7525/Screenshot%20from%202018-12-02%2021-41-38.png" title="Array#===" alt="Array#===" loading="lazy"></p>
<p>To duplicate this behavior provide the following as input:</p>
<pre><code>"-10\n+18\n+5\n+1\n+1\n-19\n-13\n-4\n-4\n-5\n-17\n+13\n-3\n+18\n-17\n+14\n+11\n+14\n+16\n+6\n-2\n-3\n-3\n-5\n+18\n+17\n-9\n+14\n+13\n+3\n-17\n-3\n+11\n-4\n-5\n+3\n+9\n-20\n-18\n+10\n+1\n+1\n-14\n+9\n-5\n+20\n-6\n+1\n+2\n+2\n-13\n-11\n+18\n+18\n+1\n+2\n-11\n+23\n+2\n-7\n+2\n+7\n-3\n+6\n+9\n+8\n+13\n-8\n+12\n+7\n+4\n+9\n-11\n-19\n+1\n+13\n+15\n-14\n+10\n+19\n-6\n+1\n+7\n-14\n+3\n+17\n+2\n+2\n+15\n+15\n+18\n+6\n-9\n+8\n+15\n+12\n+15\n+5\n+8\n+1\n+6\n-13\n+18\n+10\n+10\n+7\n+14\n+4\n+9\n+17\n+10\n+6\n+7\n+9\n+5\n+1\n+1\n+19\n+10\n+18\n-5\n+10\n+7\n-6\n-10\n+17\n-12\n-15\n-17\n+5\n+7\n-11\n+18\n-12\n-12\n-3\n+10\n-4\n-5\n+13\n+10\n-1\n+7\n-12\n-11\n-9\n-18\n+3\n-1\n-15\n-7\n-15\n+4\n-7\n-4\n-7\n+19\n-3\n+14\n+9\n-11\n-7\n+16\n-10\n-3\n+10\n+13\n+10\n-7\n+13\n+11\n+17\n+7\n+4\n+20\n+19\n-1\n-5\n+10\n+7\n-9\n-14\n-3\n-15\n+5\n-19\n+13\n+9\n-12\n-6\n-13\n-15\n-2\n-15\n-3\n+11\n+22\n+19\n+18\n-6\n+10\n-9\n+10\n+19\n-15\n-2\n+20\n+12\n-20\n-8\n+23\n+15\n-11\n+10\n-2\n+8\n-4\n-19\n+16\n+16\n-6\n-22\n-2\n+9\n+13\n-19\n+8\n+16\n+18\n+21\n+17\n+26\n-19\n+16\n+8\n-14\n-1\n+8\n+9\n+2\n+6\n+4\n-7\n-2\n+1\n+14\n-3\n+17\n+6\n+19\n-14\n+10\n+13\n-17\n-10\n+11\n-14\n-13\n-13\n+11\n+19\n+18\n+1\n-12\n+14\n-17\n+8\n+11\n+1\n+15\n+13\n-12\n+14\n+2\n-8\n+9\n+9\n+2\n+14\n+7\n+14\n-1\n-11\n+13\n-11\n-3\n-18\n+7\n-19\n-1\n-14\n+4\n-11\n+12\n-6\n-19\n+6\n+15\n-10\n-9\n+24\n-9\n-1\n+14\n+8\n-5\n-5\n+12\n+16\n-14\n+3\n-6\n+12\n+11\n-18\n+9\n+17\n+10\n+11\n-19\n+13\n+9\n+4\n+15\n+8\n-21\n+5\n-12\n+4\n+13\n+13\n+6\n+1\n+6\n+4\n+6\n-14\n-6\n+17\n-4\n+10\n+13\n+17\n+3\n-5\n+19\n+6\n-16\n-8\n+21\n-19\n+4\n-15\n-5\n+7\n-11\n-19\n+18\n-2\n+10\n-17\n-8\n-8\n-10\n+7\n-19\n-6\n-11\n+19\n+5\n+9\n-11\n+16\n-13\n-17\n+5\n-18\n-1\n+12\n-9\n-18\n+25\n-3\n-8\n-15\n+9\n-19\n-5\n+18\n+5\n+3\n-1\n-12\n-12\n+8\n-21\n+3\n+1\n-32\n-8\n+2\n-3\n+27\n+12\n+38\n-17\n+42\n+27\n+10\n+5\n-1\n-1\n+10\n-17\n+11\n+18\n+2\n-19\n-11\n+18\n+7\n+23\n-5\n+21\n-20\n+2\n-6\n-20\n-7\n+16\n-8\n+41\n+15\n-3\n-18\n+16\n+3\n-2\n+16\n+8\n-1\n+3\n+17\n+21\n+6\n+19\n+8\n-14\n+8\n+4\n-1\n+10\n+7\n-9\n-20\n-9\n-60\n+40\n-14\n-19\n+38\n-52\n-13\n-203\n-31\n-15\n+1\n-9\n-12\n+17\n+10\n-9\n-5\n-21\n-5\n-6\n-11\n+19\n+10\n-11\n-16\n-37\n-22\n-13\n+5\n+19\n-14\n-7\n+13\n-8\n+26\n+16\n+19\n-7\n+28\n+16\n-2\n+18\n+27\n+13\n-150\n+5\n+22\n-6\n-22\n-14\n-136\n-91\n-7\n-14\n+31\n-278\n-73081\n+12\n+15\n-16\n+6\n-8\n-3\n+19\n-3\n+10\n+1\n+1\n+8\n+9\n+9\n-12\n+9\n-2\n+14\n+9\n-19\n+15\n+21\n+19\n+1\n+3\n+19\n-11\n+8\n+20\n-14\n+16\n+4\n+6\n-16\n-3\n-3\n-13\n-4\n+5\n+16\n-5\n-10\n+3\n-19\n-5\n+7\n-16\n-7\n+10\n+1\n+18\n+10\n-12\n-14\n-15\n-7\n+14\n+12\n+16\n+17\n+11\n+4\n+12\n+15\n-17\n+13\n-8\n+1\n-12\n-16\n-10\n-9\n-10\n+8\n-20\n+8\n-5\n-7\n-16\n+9\n-8\n-13\n-12\n-8\n+2\n+3\n+16\n-15\n+11\n+11\n+2\n-3\n-17\n-17\n-3\n-7\n-20\n+18\n-9\n+3\n-5\n-10\n-17\n+16\n-2\n-19\n-18\n-12\n-14\n-17\n-3\n+6\n+10\n+16\n+3\n+2\n-16\n-16\n-10\n-10\n+14\n-6\n-10\n+9\n+15\n+15\n+7\n-14\n-2\n+10\n-14\n-11\n-2\n+14\n+16\n+5\n+20\n+12\n-18\n+11\n+9\n+9\n-3\n-5\n+12\n+15\n+6\n-8\n+3\n+14\n+15\n-6\n-12\n-15\n+23\n-7\n+18\n-4\n+18\n+4\n+9\n+19\n-7\n+6\n+3\n-10\n+18\n-19\n-20\n-6\n+17\n-15\n+3\n+20\n-5\n-10\n-12\n-23\n+5\n-1\n-14\n-16\n-17\n-12\n+17\n-14\n+4\n-12\n+18\n+20\n-15\n-19\n-1\n-15\n+10\n-9\n+1\n+3\n-18\n+19\n-14\n-19\n+17\n-11\n-3\n-13\n+7\n+19\n-15\n+7\n-33\n-8\n+2\n+2\n-18\n-10\n+16\n-7\n+4\n-14\n+8\n+13\n-5\n+20\n-14\n+15\n-11\n-7\n-22\n-10\n+11\n+1\n+16\n-8\n+16\n-3\n+15\n+6\n-17\n+27\n+14\n+15\n+8\n+18\n+21\n-19\n-25\n+11\n+10\n+65\n-11\n-36\n-15\n-11\n-25\n+18\n+35\n+72\n+1\n+58\n+3\n+12\n+19\n-10\n+21\n+16\n+11\n+9\n+1\n+1\n+9\n-6\n+20\n-12\n-20\n+5\n+8\n-7\n+18\n+19\n-13\n-15\n-24\n+8\n-16\n+3\n+2\n-14\n-1\n-10\n-16\n-17\n+21\n+4\n+14\n-17\n+18\n-12\n+10\n+11\n+2\n-15\n-4\n-19\n+13\n+1\n-18\n-6\n-23\n-17\n+19\n+28\n+6\n+29\n+10\n+17\n-6\n+5\n-11\n+26\n+25\n-22\n+2\n-10\n-29\n+43\n+17\n+5\n+4\n+26\n+1\n+11\n+19\n-12\n+20\n+17\n-13\n+1\n+19\n+14\n-19\n-9\n+2\n+13\n+4\n-2\n+19\n+10\n-14\n+10\n-9\n+1\n+20\n+16\n+6\n-13\n+4\n+19\n+16\n-6\n-7\n-25\n-20\n+5\n+2\n-3\n-9\n-21\n-19\n+12\n-8\n-7\n+17\n-15\n-18\n-11\n+6\n+3\n+15\n-5\n-5\n-6\n-18\n-5\n+19\n-5\n+18\n-1\n+2\n-16\n-6\n-16\n+17\n-8\n+16\n+30\n+18\n+5\n-2\n+16\n+19\n-8\n+9\n-23\n+12\n+3\n+18\n+36\n+50\n-133\n+7\n+9\n-68\n+7\n+2\n-113\n-85\n-23\n-211\n-19\n-6\n-21\n-11\n-16\n+19\n+15\n-13\n-4\n+14\n+27\n-12\n-5\n-18\n-20\n-16\n-15\n-15\n-12\n+1\n+6\n+9\n-11\n+18\n+5\n-14\n-19\n-9\n+18\n+2\n-18\n-11\n+3\n+13\n-4\n-4\n+9\n-10\n-17\n-4\n+16\n+13\n+19\n-15\n+6\n-3\n+4\n+10\n+20\n+17\n-24\n-5\n+1\n+8\n+27\n+6\n+4\n+20\n+8\n-3\n+66\n-139\n-21\n+11\n-19\n+20\n-13\n-31\n+7\n-2\n+5\n-2\n+4\n-16\n+7\n+6\n-21\n-10\n-12\n+25\n-7\n-17\n-13\n+73906"
</code></pre>
<p>The last jump in memory size was from 7ish Gigs to 10ish Gigs.</p>
<p>Does Ruby need to continually allocate more memory when using <code>Array#===</code>?</p>
Ruby master - Bug #13939 (Rejected): Ruby 2.4.2 has issue supporting Seattle.rb style for define_...
https://redmine.ruby-lang.org/issues/13939
2017-09-25T15:43:39Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>In Ruby 2.3 & 2.4.0 you can do this</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">define_method</span> <span class="ss">:some_method_name</span> <span class="p">{</span> <span class="s2">"asdf"</span> <span class="p">}</span>
</code></pre>
<p>As of my trying 2.4.2 this is no longer supported. Anyone who tries to load my 'read_source' gem will get a failure message in require without explaining the specific area of code.</p>
<pre><code>SyntaxError: /home/danielpclark/dev/read_source/test/support/example.rb:18: syntax error, unexpected '{', expecting keyword_end
ethod :also_attr_method_name { "asdf" }
^
/home/danielpclark/dev/read_source/test/support/example.rb:18: syntax error, unexpected '}', expecting keyword_end
so_attr_method_name { "asdf" }
^
from (irb):2:in `require_relative'
from (irb):2
from /usr/share/rvm/rubies/ruby-2.4.2/bin/irb:11:in `<main>'
</code></pre>
<p>To fix my gem for Ruby 2.4.2 I now have to wrap the method name in parenthesis <code>()</code></p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">define_method</span><span class="p">(</span><span class="ss">:some_method_name</span><span class="p">)</span> <span class="p">{</span> <span class="s2">"asdf"</span> <span class="p">}</span>
</code></pre>
<p>And that will work. But I find this odd as the following will still work in 2.4.2:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">define_method</span> <span class="ss">:johny</span><span class="p">,</span> <span class="nb">instance_method</span><span class="p">(</span><span class="ss">:apple</span><span class="p">)</span>
</code></pre>
<p>Which is still Seattle.rb style.</p>
Ruby master - Feature #13601 (Closed): Remove yield_self from Ruby 2.5 (already implemented)
https://redmine.ruby-lang.org/issues/13601
2017-05-26T19:35:25Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>Issue <a href="https://bugs.ruby-lang.org/issues/6721" class="external">https://bugs.ruby-lang.org/issues/6721</a> for adding <code>yield_self</code> is unnecessary as <code>BasicObject#instance_eval</code> will do the exact same thing.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">BasicObject</span>
<span class="k">alias</span> <span class="ss">:yield_self</span> <span class="ss">:instance_eval</span>
<span class="k">end</span>
<span class="mi">2</span><span class="p">.</span><span class="nf">yield_self</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="p">}</span> <span class="c1"># => 4</span>
</code></pre>
<p>I've tried all the examples of its given use cases and <code>BasicObject#instance_eval</code> will do them all.</p>
<p>In issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Object#yield_self (Closed)" href="https://redmine.ruby-lang.org/issues/6721">#6721</a> nobu said he didn't like the name <code>yield_self</code>. I'm in agreement about the name. Since <code>BasicObject#instance_eval</code> will already pipe in <code>self</code> and return the value of the block <code>yield_self</code> is not necessary.</p>
Ruby master - Feature #12281 (Assigned): Allow lexically scoped use of refinements with `using {}...
https://redmine.ruby-lang.org/issues/12281
2016-04-14T03:48:01Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>In Ruby 2.2.3 a refinement could be used in a begin/end block.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Moo</span>
<span class="n">refine</span> <span class="no">Fixnum</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">to_s</span>
<span class="s2">"moo"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">begin</span> <span class="c1"># valid Ruby 2.2.3 and NOT Ruby 2.3</span>
<span class="n">using</span> <span class="no">Moo</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">to_s</span>
<span class="k">end</span>
<span class="c1"># => "moo"</span>
</code></pre>
<p>Since this use case has been removed I would like to propose an alternative.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">using</span> <span class="no">Moo</span> <span class="k">do</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">to_s</span>
<span class="k">end</span>
<span class="c1"># => "moo"</span>
</code></pre>
<p>I would like to propose allowing refinements to take a block and perform the refinement within the block and work just as if it were in it's own lexically scoped class.</p>
<p>I've been writing a lot of Rust lately and have found that their way of implementing Traits is just like Ruby's refinements except for that you can use Rust's version of refinements anywhere. Since Ruby's implementation is strictly lexically scoped I merely suggest a block syntax for <code>using</code> to allow greater expansion of refinements.</p>
<pre><code class="rust syntaxhl" data-language="rust"><span class="c1">// Rust</span>
<span class="k">impl</span> <span class="n">MyCapitalize</span> <span class="k">for</span> <span class="nb">String</span> <span class="p">{</span>
<span class="k">fn</span> <span class="nf">my_capitalize</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="k">Self</span> <span class="p">{</span>
<span class="c1">// code here</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">use</span> <span class="n">MyCapitalize</span><span class="p">;</span>
<span class="nn">String</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="s">"hello"</span><span class="p">)</span><span class="nf">.my_capitalize</span><span class="p">()</span>
</code></pre>
<p>Rust lets you use the "refinement" of the trait implementation anywhere you use <code>use</code> just like Ruby's <code>using</code>. But currently Ruby restricts where <code>using</code> can be used. I would like that restriction to be lifted by allowing <code>using</code> to take a block.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Ruby</span>
<span class="k">module</span> <span class="nn">MyCapitalize</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">my_capitalize</span>
<span class="c1"># code here</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">using</span> <span class="no">MyCapitalize</span> <span class="k">do</span>
<span class="s2">"hello"</span><span class="p">.</span><span class="nf">my_capitalize</span>
<span class="k">end</span>
<span class="c1"># => "Hello"</span>
</code></pre>
<p>This way we keep Ruby's strict lexical scope behavior and at the same time allow refinement usage anywhere we need it.</p>
Ruby master - Bug #11980 (Closed): External methods are appearing as instance methods for String
https://redmine.ruby-lang.org/issues/11980
2016-01-12T12:30:24Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>It appears we're having methods creep into the String scope.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="s2">""</span><span class="p">.</span><span class="nf">methods</span><span class="p">.</span><span class="nf">count</span>
<span class="c1"># => 170</span>
<span class="k">defined?</span> <span class="s2">""</span><span class="p">.</span><span class="nf">a</span>
<span class="c1"># => nil</span>
<span class="k">def</span> <span class="nf">a</span>
<span class="s2">"foo"</span>
<span class="k">end</span>
<span class="s2">""</span><span class="p">.</span><span class="nf">methods</span><span class="p">.</span><span class="nf">count</span>
<span class="c1"># => 171</span>
<span class="k">defined?</span> <span class="s2">""</span><span class="p">.</span><span class="nf">a</span>
<span class="c1"># => "method"</span>
<span class="s2">"bar"</span><span class="p">.</span><span class="nf">a</span>
<span class="c1"># => "foo"</span>
</code></pre>
Ruby master - Bug #11828 (Rejected): Object#freeze grid-locks Ruby
https://redmine.ruby-lang.org/issues/11828
2015-12-17T01:01:02Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>It seems safe to freeze most any class type in Ruby. But if you call <code>Object.freeze</code> nothing from then on can be created in either class of method form.</p>
<p>Is this okay behavior to have in Ruby?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Object</span><span class="p">.</span><span class="nf">freeze</span>
<span class="k">class</span> <span class="nc">A</span>
<span class="k">end</span>
<span class="c1"># => RuntimeError: can't modify frozen #<Class:Object></span>
<span class="k">def</span> <span class="nf">x</span>
<span class="k">end</span>
<span class="c1"># => RuntimeError: can't modify frozen class</span>
</code></pre>
<p>I noticed that Procs can still be defined.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">prc</span> <span class="o">=</span> <span class="nb">proc</span> <span class="p">{</span><span class="o">|</span><span class="n">a</span><span class="o">|</span> <span class="n">a</span><span class="o">+</span><span class="mi">1</span><span class="p">}</span>
<span class="n">prc</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="c1"># => 5 </span>
</code></pre>
<p>But all singleton instances are frozen.</p>
Ruby master - Feature #11824 (Feedback): Add Enumerator#to_ary for added implicit behavior
https://redmine.ruby-lang.org/issues/11824
2015-12-15T20:39:36Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>Calling <code>Enumerator#to_a</code> many times can become a bit ugly in a code base. I propose these changes to Enumerator to allow implicit Array use of all Enumerators.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Enumerator</span>
<span class="k">def</span> <span class="nf">to_ary</span>
<span class="nb">to_a</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">method_missing</span> <span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">&</span><span class="n">b</span>
<span class="k">return</span> <span class="nb">to_a</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="o">*</span><span class="n">a</span><span class="p">,</span> <span class="o">&</span><span class="n">b</span><span class="p">)</span> <span class="k">if</span> <span class="no">Array</span><span class="p">.</span><span class="nf">instance_methods</span><span class="p">.</span><span class="nf">include?</span> <span class="n">m</span>
<span class="k">super</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
Ruby master - Bug #11772 (Closed): Implicit conversion of Array in String interpolation does not ...
https://redmine.ruby-lang.org/issues/11772
2015-12-05T05:22:39Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>While providing an example in <a href="https://bugs.ruby-lang.org/issues/10930#note-7" class="external">https://bugs.ruby-lang.org/issues/10930#note-7</a> I found that the implicit changing of an Array calls to_s without trying to_str first. Isn't String interpolation "implicitly" converting items to strings?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Array</span>
<span class="k">def</span> <span class="nf">to_str</span>
<span class="s2">"Hello from Array!"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="s2">"</span><span class="si">#{</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="si">}</span><span class="s2">"</span>
<span class="c1"># => [1, 2, 3, 4, 5]</span>
</code></pre>
<p>I believe String interpolation should call <code>to_str</code> before <code>to_s</code></p>
Ruby master - Feature #11737 (Rejected): Pass in expression to then block in `case expression`
https://redmine.ruby-lang.org/issues/11737
2015-11-24T20:59:22Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>Ruby's <code>case <expression></code> scenario allows the expression to be tested in the <code>when</code> test with <code>:===</code>, but in the then block the expression is not accessible. Only if the expression has been assigned to a variable beforehand can it be checked.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">case</span> <span class="mi">4</span>
<span class="k">when</span> <span class="o">-></span><span class="n">i</span><span class="p">{</span> <span class="nb">puts</span> <span class="ss">:when</span><span class="p">;</span> <span class="kp">true</span><span class="p">}</span>
<span class="o">-></span><span class="n">i</span><span class="p">{</span> <span class="nb">puts</span> <span class="n">i</span><span class="p">}</span>
<span class="k">else</span>
<span class="ss">:foo</span>
<span class="k">end</span>
<span class="c1"># when</span>
<span class="c1"># => #<Proc:0x00000000d91e58@(irb):16 (lambda)> </span>
<span class="k">case</span> <span class="mi">4</span>
<span class="k">when</span> <span class="o">-></span><span class="n">i</span><span class="p">{</span> <span class="nb">puts</span> <span class="ss">:when</span><span class="p">;</span> <span class="kp">true</span><span class="p">}</span>
<span class="nb">puts</span> <span class="n">_</span>
<span class="k">else</span>
<span class="ss">:foo</span>
<span class="k">end</span>
<span class="c1"># when</span>
<span class="c1"># #<Proc:0x00000000d91e58@(irb):16 (lambda)></span>
<span class="c1"># => nil </span>
<span class="k">case</span> <span class="mi">4</span>
<span class="k">when</span> <span class="mi">4</span>
<span class="k">then</span> <span class="n">_</span>
<span class="k">end</span>
<span class="c1"># => nil</span>
<span class="k">case</span> <span class="mi">4</span>
<span class="k">when</span> <span class="mi">4</span>
<span class="k">then</span> <span class="o">-></span><span class="n">i</span><span class="p">{</span><span class="nb">puts</span> <span class="n">i</span><span class="p">}</span>
<span class="k">end</span>
<span class="c1"># => #<Proc:0x000000015f9be0@(irb):36 (lambda)> </span>
</code></pre>
<p>If some one wanted to give an expression after case that wasn't assigned to a variable then there is no access to it in the then block.</p>
<p>I suggest assigning the expression to the <code>_</code> variable during a case/when/then scenario. Here's a rather contrived example use case.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">case</span> <span class="no">Enumerator</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span> <span class="o">|</span><span class="n">y</span><span class="o">|</span> <span class="n">y</span> <span class="o"><<</span> <span class="mi">1</span><span class="p">;</span> <span class="n">y</span> <span class="o"><<</span> <span class="mi">2</span><span class="p">;</span> <span class="n">y</span> <span class="o"><<</span> <span class="mi">3</span><span class="p">;</span> <span class="k">end</span>
<span class="k">when</span> <span class="o">-></span><span class="n">e</span><span class="p">{</span> <span class="mi">2</span><span class="p">.</span><span class="nf">times</span> <span class="n">e</span><span class="p">.</span><span class="nf">next</span><span class="p">;</span> <span class="kp">true</span><span class="p">}</span>
<span class="k">then</span> <span class="n">_</span><span class="p">.</span><span class="nf">peek</span>
<span class="k">end</span> <span class="o">==</span> <span class="mi">3</span>
</code></pre>
Ruby master - Bug #11704 (Rejected): Refinements only get "used" once in loop
https://redmine.ruby-lang.org/issues/11704
2015-11-17T23:08:10Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>Same results on Ruby 2.2.2 through Ruby 2.3.0dev (2015-11-18 trunk 52625) [x86_64-linux]</p>
<p>I wrote a benchmark for testing different ways of implementing a <code>uniq</code> method and I chose to do it using refinements. I looped over the results in the benchmark and refined the method with 6 different refinements which each worked. But the next iteration when <code>using</code> is called it doesn't re-refine with previously used refinements.</p>
<p>Example benchmark output on first iteration:</p>
<pre><code>Array.new(200) !self.dup.uniq! 1.770000 0.010000 1.780000 ( 1.778248)
Array.new(200) == uniq.length 1.860000 0.000000 1.860000 ( 1.866862)
Array.new(200) == uniq.sort 2.580000 0.010000 2.590000 ( 2.584515)
Array.new(200) each index 41.450000 0.080000 41.530000 ( 41.626149)
Array.new(200) combination(2) 23.460000 0.060000 23.520000 ( 23.568865)
Array.new(200) == self.uniq 1.900000 0.010000 1.910000 ( 1.909466)
</code></pre>
<p>After that the same methods did not get refined.</p>
<pre><code>Array.new(210) !self.dup.uniq! 1.990000 0.000000 1.990000 ( 2.004269)
Array.new(210) == uniq.length 2.030000 0.010000 2.040000 ( 2.032602)
Array.new(210) == uniq.sort 1.990000 0.000000 1.990000 ( 1.999509)
Array.new(210) each index 1.990000 0.010000 2.000000 ( 2.000181)
Array.new(210) combination(2) 2.000000 0.000000 2.000000 ( 2.010159)
Array.new(210) == self.uniq 2.000000 0.010000 2.010000 ( 2.009117)
Array.new(220) !self.dup.uniq! 2.100000 0.010000 2.110000 ( 2.113701)
Array.new(220) == uniq.length 2.070000 0.000000 2.070000 ( 2.075249)
Array.new(220) == uniq.sort 2.090000 0.010000 2.100000 ( 2.102771)
Array.new(220) each index 2.070000 0.000000 2.070000 ( 2.077393)
Array.new(220) combination(2) 2.070000 0.010000 2.080000 ( 2.079561)
Array.new(220) == self.uniq 2.100000 0.010000 2.110000 ( 2.110839)
Array.new(230) !self.dup.uniq! 2.210000 0.000000 2.210000 ( 2.236008)
Array.new(230) == uniq.length 2.160000 0.010000 2.170000 ( 2.166484)
Array.new(230) == uniq.sort 2.140000 0.000000 2.140000 ( 2.150384)
Array.new(230) each index 2.130000 0.010000 2.140000 ( 2.134572)
Array.new(230) combination(2) 2.120000 0.000000 2.120000 ( 2.129683)
Array.new(230) == self.uniq 2.130000 0.010000 2.140000 ( 2.137515)
</code></pre>
<p>I found no way to inspect what code was being used as refinements currently don't allow introspection (I have read the Refinement Specs <a href="https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RefinementsSpec" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RefinementsSpec</a> ). But I figure if I wanted to see what the refinement was I could write an additional method to document the current refinement in use.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">BooleanUniqWithEqualLength</span>
<span class="n">refine</span> <span class="no">Array</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">uniq?</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">length</span> <span class="o">==</span> <span class="nb">self</span><span class="p">.</span><span class="nf">uniq</span><span class="p">.</span><span class="nf">length</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">which_refinement_uniq?</span>
<span class="s2">"self.length == self.uniq.length"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>But introspection is not the issue I'm raising here. The issue is that you can only use the refinement once within the scope of the loop. Look at the benchmark results and see the first 6 are correct, and the following 3 times the output is lying about what refinement is being used.</p>
<p>Here's the full benchmark code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'securerandom'</span>
<span class="nb">require</span> <span class="s1">'benchmark'</span>
<span class="c1"># written to allow 65,536 unique array items</span>
<span class="n">array_of_x</span> <span class="o">=</span> <span class="nb">lambda</span> <span class="p">{</span><span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="no">SecureRandom</span><span class="p">.</span><span class="nf">hex</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="mi">2</span><span class="p">).</span><span class="nf">scan</span><span class="p">(</span><span class="sr">/..../</span><span class="p">)</span> <span class="p">}</span>
<span class="k">module</span> <span class="nn">Refinements</span>
<span class="k">module</span> <span class="nn">BooleanUniqWithDupUniqBang</span>
<span class="n">refine</span> <span class="no">Array</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">uniq?</span>
<span class="o">!</span><span class="nb">self</span><span class="p">.</span><span class="nf">dup</span><span class="p">.</span><span class="nf">uniq!</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">BooleanUniqWithEqualLength</span>
<span class="n">refine</span> <span class="no">Array</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">uniq?</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">length</span> <span class="o">==</span> <span class="nb">self</span><span class="p">.</span><span class="nf">uniq</span><span class="p">.</span><span class="nf">length</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">BooleanUniqWithEqualSort</span>
<span class="n">refine</span> <span class="no">Array</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">uniq?</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">sort</span> <span class="o">==</span> <span class="nb">self</span><span class="p">.</span><span class="nf">uniq</span><span class="p">.</span><span class="nf">sort</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">BooleanUniqWithEachIndex</span>
<span class="n">refine</span> <span class="no">Array</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">uniq?</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">each_with_index</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="nb">self</span><span class="p">.</span><span class="nf">each_with_index</span> <span class="p">{</span> <span class="o">|</span><span class="n">c</span><span class="p">,</span><span class="n">d</span><span class="o">|</span>
<span class="k">next</span> <span class="k">if</span> <span class="n">b</span> <span class="o">==</span> <span class="n">d</span>
<span class="k">return</span> <span class="kp">false</span> <span class="k">if</span> <span class="n">a</span> <span class="o">==</span> <span class="n">c</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">BooleanUniqWithCombination</span>
<span class="n">refine</span> <span class="no">Array</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">uniq?</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">combination</span><span class="p">(</span><span class="mi">2</span><span class="p">).</span><span class="nf">each</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="k">return</span> <span class="kp">false</span> <span class="k">if</span> <span class="n">a</span> <span class="o">==</span> <span class="n">b</span><span class="p">}</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">BooleanUniqWithUniq</span>
<span class="n">refine</span> <span class="no">Array</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">uniq?</span>
<span class="nb">self</span> <span class="o">==</span> <span class="nb">self</span><span class="p">.</span><span class="nf">uniq</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">bench_reps</span> <span class="o">=</span> <span class="mi">10_000</span>
<span class="n">bench</span> <span class="o">=</span> <span class="no">Benchmark</span><span class="p">.</span><span class="nf">benchmark</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">Testing various ways of implementing :uniq? on Array</span><span class="se">\n</span><span class="s2">(smaller numbers are better)</span><span class="se">\n\n</span><span class="s2">"</span><span class="p">,</span><span class="mi">34</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="c1"># Note doing anymore than one test per test type seems to wash the results into all things being equal.</span>
<span class="c1"># Only the first test gives realistic numbers.</span>
<span class="p">[</span><span class="mi">500</span><span class="p">].</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">qty</span><span class="o">|</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Array.new(</span><span class="si">#{</span><span class="n">qty</span><span class="si">}</span><span class="s2">) !self.dup.uniq!"</span><span class="p">)</span> <span class="p">{</span>
<span class="n">using</span> <span class="no">Refinements</span><span class="o">::</span><span class="no">BooleanUniqWithDupUniqBang</span>
<span class="n">bench_reps</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">array_of_x</span><span class="o">.</span><span class="p">(</span><span class="n">qty</span><span class="p">).</span><span class="nf">uniq?</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Array.new(</span><span class="si">#{</span><span class="n">qty</span><span class="si">}</span><span class="s2">) == uniq.length"</span><span class="p">)</span> <span class="p">{</span>
<span class="n">using</span> <span class="no">Refinements</span><span class="o">::</span><span class="no">BooleanUniqWithEqualLength</span>
<span class="n">bench_reps</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">array_of_x</span><span class="o">.</span><span class="p">(</span><span class="n">qty</span><span class="p">).</span><span class="nf">uniq?</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Array.new(</span><span class="si">#{</span><span class="n">qty</span><span class="si">}</span><span class="s2">) == uniq.sort"</span><span class="p">)</span> <span class="p">{</span>
<span class="n">using</span> <span class="no">Refinements</span><span class="o">::</span><span class="no">BooleanUniqWithEqualSort</span>
<span class="n">bench_reps</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">array_of_x</span><span class="o">.</span><span class="p">(</span><span class="n">qty</span><span class="p">).</span><span class="nf">uniq?</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Array.new(</span><span class="si">#{</span><span class="n">qty</span><span class="si">}</span><span class="s2">) each index"</span><span class="p">)</span> <span class="p">{</span>
<span class="n">using</span> <span class="no">Refinements</span><span class="o">::</span><span class="no">BooleanUniqWithEachIndex</span>
<span class="n">bench_reps</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">array_of_x</span><span class="o">.</span><span class="p">(</span><span class="n">qty</span><span class="p">).</span><span class="nf">uniq?</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Array.new(</span><span class="si">#{</span><span class="n">qty</span><span class="si">}</span><span class="s2">) combination(2)"</span><span class="p">)</span> <span class="p">{</span>
<span class="n">using</span> <span class="no">Refinements</span><span class="o">::</span><span class="no">BooleanUniqWithCombination</span>
<span class="n">bench_reps</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">array_of_x</span><span class="o">.</span><span class="p">(</span><span class="n">qty</span><span class="p">).</span><span class="nf">uniq?</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Array.new(</span><span class="si">#{</span><span class="n">qty</span><span class="si">}</span><span class="s2">) == self.uniq"</span><span class="p">)</span> <span class="p">{</span>
<span class="n">using</span> <span class="no">Refinements</span><span class="o">::</span><span class="no">BooleanUniqWithUniq</span>
<span class="n">bench_reps</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="n">array_of_x</span><span class="o">.</span><span class="p">(</span><span class="n">qty</span><span class="p">).</span><span class="nf">uniq?</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
Ruby master - Feature #11690 (Open): Update Hash during multiple assignment
https://redmine.ruby-lang.org/issues/11690
2015-11-15T16:30:53Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>Given that we can assign multiple variables at once</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">,</span><span class="n">c</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span>
</code></pre>
<p>It would be nice to be able to update a Hash during multiple assignment rather than replacing it. Currently</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">x</span> <span class="o">=</span> <span class="p">{</span><span class="ss">a: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">2</span><span class="p">}</span>
<span class="n">x</span><span class="p">,</span> <span class="n">y</span> <span class="p">,</span><span class="n">z</span> <span class="o">=</span> <span class="p">{</span><span class="ss">c: </span><span class="mi">3</span><span class="p">},</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span>
<span class="n">x</span>
<span class="c1"># => {c: 3}</span>
</code></pre>
<p>What I propose is adding <code>Hash#update=</code> to permit updating during multiple assignment.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Hash</span>
<span class="k">def</span> <span class="nf">update</span><span class="o">=</span><span class="p">(</span><span class="n">h</span><span class="p">)</span>
<span class="n">update</span><span class="p">(</span><span class="n">h</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">{</span><span class="ss">a: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">2</span><span class="p">}</span>
<span class="n">x</span><span class="p">.</span><span class="nf">update</span><span class="p">,</span> <span class="n">y</span> <span class="p">,</span><span class="n">z</span> <span class="o">=</span> <span class="p">{</span><span class="ss">c: </span><span class="mi">3</span><span class="p">},</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span>
<span class="n">x</span>
<span class="c1"># => {a: 1, b: 2, c: 3}</span>
</code></pre>
<p>This would be most useful in scenarios where a method or proc return multiple values. When the method returns the values we don't normally know the key outside where the hash assignment is.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">example</span> <span class="o">=</span> <span class="nb">proc</span> <span class="p">{</span> <span class="p">[{</span><span class="ss">:hi</span> <span class="o">=></span> <span class="ss">:hello</span><span class="p">},</span> <span class="mi">5</span><span class="p">]</span> <span class="p">}</span>
<span class="nb">hash</span> <span class="o">=</span> <span class="p">{}</span>
<span class="c1"># Currently in Ruby with an Unknown key multiple assignment isn't an option</span>
<span class="nb">hash</span><span class="p">[</span><span class="sc">??</span><span class="p">?</span><span class="sc">?]</span><span class="p">,</span> <span class="n">current</span> <span class="o">=</span> <span class="n">example</span><span class="p">.</span><span class="nf">call</span>
<span class="c1"># We currently have to two step it</span>
<span class="n">result</span><span class="p">,</span> <span class="n">current</span> <span class="o">=</span> <span class="n">example</span><span class="p">.</span><span class="nf">call</span>
<span class="nb">hash</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
</code></pre>
<p>But with <code>Hash#update=</code> we don't have to know the key.</p>
Ruby master - Feature #11653 (Closed): Add to_proc on Hash
https://redmine.ruby-lang.org/issues/11653
2015-11-04T02:59:15Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>Procs can be called the same way a hash is with <code>[]</code>. But a Hash is not mappable as a Proc.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="n">my_hash</span> <span class="o">=</span> <span class="o">-></span><span class="n">key</span><span class="p">{{</span>
<span class="ss">a: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">2</span><span class="p">,</span> <span class="ss">c: </span><span class="mi">3</span><span class="p">,</span> <span class="ss">d: </span><span class="mi">4</span><span class="p">,</span> <span class="ss">e: </span><span class="mi">5</span><span class="p">,</span> <span class="ss">f: </span><span class="mi">6</span>
<span class="p">}[</span><span class="n">key</span><span class="p">]}</span>
<span class="n">my_hash</span><span class="p">[</span><span class="ss">:a</span><span class="p">]</span>
<span class="c1"># => 1</span>
<span class="p">[</span><span class="ss">:e</span><span class="p">,</span> <span class="ss">:a</span><span class="p">,</span> <span class="ss">:b</span><span class="p">,</span> <span class="ss">:f</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="nf">map</span><span class="p">(</span><span class="o">&</span><span class="n">my_hash</span><span class="p">)</span> <span class="c1"># hash is now mappable</span>
<span class="c1"># => [5, 1, 2, 6, 3, 4]</span>
</code></pre>
<p>This seems so straight forward I believe it should be part of the language itself with the <code>.to_proc</code> method call.</p>
Ruby master - Feature #10930 (Feedback): Allow splat operator to work for string interpolation
https://redmine.ruby-lang.org/issues/10930
2015-03-03T14:41:23Z
danielpclark (Daniel P. Clark)
6ftdan@gmail.com
<p>Currently when you use the splat operator in a method it pulls the items out of the array for method parameters.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">foo</span><span class="p">(</span><span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">,</span><span class="n">c</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"</span><span class="si">#{</span><span class="n">a</span><span class="si">}</span><span class="s2">, </span><span class="si">#{</span><span class="n">b</span><span class="si">}</span><span class="s2">, </span><span class="si">#{</span><span class="n">c</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="n">bar</span> <span class="o">=</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="n">foo</span><span class="p">(</span><span class="o">*</span><span class="n">bar</span><span class="p">)</span>
<span class="c1"># => "1, 2, 3"</span>
</code></pre>
<p>So I would expect to be able to do "#{*bar}" and get either "1, 2, 3" or "1,2,3". But when attempting this I get.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">baz</span> <span class="o">=</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="s2">"</span><span class="si">#{</span><span class="o">*</span><span class="n">baz</span><span class="si">}</span><span class="s2">"</span>
<span class="c1"># SyntaxError: (irb):53: syntax error, unexpected tSTRING_DEND, expecting '='</span>
<span class="c1"># "#{*baz}"</span>
<span class="c1"># ^</span>
<span class="c1"># (irb):53: unterminated string meets end of file</span>
<span class="s2">"</span><span class="si">#{</span><span class="o">*</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="si">}</span><span class="s2">"</span>
<span class="c1"># SyntaxError: (irb):54: syntax error, unexpected tSTRING_DEND, expecting :: or '[' or '.'</span>
<span class="c1"># "#{*[1,2,3]}"</span>
<span class="c1"># ^</span>
<span class="c1"># (irb):54: unterminated string meets end of file</span>
</code></pre>
<p>This doesn't work on any of the Ruby versions available 1.8 through 2.2.1. They each produce the same error.</p>
<p>I propose allowing the splat operator within string interpolation to work the same as [1,2,3].join(',')</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">fiz</span> <span class="o">=</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="s2">"</span><span class="si">#{</span><span class="o">*</span><span class="n">fiz</span><span class="si">}</span><span class="s2">"</span>
<span class="c1"># => "1,2,3"</span>
<span class="s2">"</span><span class="si">#{</span><span class="o">*</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="si">}</span><span class="s2">"</span>
<span class="c1"># => "1,2,3"</span>
</code></pre>