Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112014-12-31T19:35:39ZRuby Issue Tracking System
Redmine Ruby master - Feature #10683 (Open): fix inconsistent behavior of Kernel.Hash()https://bugs.ruby-lang.org/issues/106832014-12-31T19:35:39Zrecursive-madman (Recursive Madman)recursive.madman@gmx.de
<p>I find the way the global function <code>Hash</code> (aka <code>Kernel.Hash</code>) works a bit confusing.</p>
<p>To illustrate:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Hash</span><span class="p">(</span><span class="kp">nil</span><span class="p">)</span> <span class="c1">#=> {} (1)</span>
<span class="no">Hash</span><span class="p">({})</span> <span class="c1">#=> {} (2)</span>
<span class="no">Hash</span><span class="p">([])</span> <span class="c1">#=> {} (3)</span>
<span class="c1"># but</span>
<span class="no">Hash</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="c1">#! TypeError (4)</span>
</code></pre>
<p>Case (1) and (2) make perfect sense to me (calling <code>Hash(var)</code> when <code>var</code> is an optional argument defaulting to <code>nil</code> will always give a (possibly empty) Hash or a TypeError, which is very useful).<br>
Case (3) however seems inconsistent, since (4) doesn't work.</p>
<p>To contrast this with the respective <code>String</code> function:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">String</span><span class="p">([])</span> <span class="c1">#=> "[]"</span>
<span class="no">String</span><span class="p">(</span><span class="s1">''</span><span class="p">)</span> <span class="c1">#=> ""</span>
<span class="no">String</span><span class="p">({})</span> <span class="c1">#=> "{}"</span>
<span class="no">String</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="c1">#=> "0"</span>
<span class="no">String</span><span class="p">(</span><span class="kp">nil</span><span class="p">)</span> <span class="c1">#=> ""</span>
</code></pre>
<p>it seems that calling <code>String(obj)</code> is equivalent to calling <code>obj.to_s</code>.</p>
<p>Thus I would assume <code>Hash(obj)</code> being equivalent to calling <code>obj.to_h</code>.</p>
<p>It is not though (calling <code>to_h</code> on <code>[[1,2]]</code> gives <code>{1=>2}</code>, while using <code>Hash()</code> raises a <code>TypeError</code>).</p>
<p>I propose to do <strong>one</strong> of the following changes:</p>
<ul>
<li>either remove the special handling of <code>[]</code>, such that only <code>nil</code> or a <code>Hash</code> are valid values to be passed to <code>Hash()</code>, or</li>
<li>change <code>Hash()</code> to call <code>to_h</code> on it's argument, when the argument is neither <code>nil</code> nor a <code>Hash</code>.</li>
</ul> Ruby master - Feature #10617 (Closed): Change multiple assignment in conditional from parse error...https://bugs.ruby-lang.org/issues/106172014-12-18T11:07:02Zrecursive-madman (Recursive Madman)recursive.madman@gmx.de
<p>There is currently an inconsistency between regular and multiple assignment in conditionals.<br>
Regular assignment causes a <strong>warning</strong>, multiple assignment causes a <strong>parse error</strong>.</p>
<p>The historical reason for this is that in 1.8 multiple assignment would always return an Array, but since 1.9 it returns whatever the RHS evaluates to.</p>
<p><strong>Examples:</strong></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="o">=</span> <span class="kp">nil</span> <span class="c1">#=> nil</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">[]</span> <span class="c1">#=> [] (but a and b are both nil)</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span><span class="mi">2</span> <span class="c1">#=> [1, 2]</span>
</code></pre>
<p>Since multiple assignment behavior has changed, it makes sense to remove the (artificial) parse error for multiple assignments.</p>
<p>That makes it possible to test the return value of a method used for multiple assignment without having to use a temporary variable.</p>
<p><strong>Example:</strong></p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># CURRENTLY WORKING CODE:</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">some_method_returning_array_or_nil</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">tmp</span>
<span class="k">if</span> <span class="n">tmp</span>
<span class="c1"># method returned an array (possibly empty)</span>
<span class="k">else</span>
<span class="c1"># method returned nil.</span>
<span class="k">end</span>
<span class="c1"># PROPOSED WORKING CODE:</span>
<span class="k">if</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">some_method_returning_array_or_nil</span><span class="p">)</span>
<span class="c1"># method returned an array (possibly empty)</span>
<span class="k">else</span>
<span class="c1"># method returned nil</span>
<span class="k">end</span>
</code></pre>
<p>(the parenthesis are needed due to LALR limitations, as discussed in <a class="issue tracker-1 status-6 priority-4 priority-default closed" title="Bug: multiple assignment in conditional (Rejected)" href="https://bugs.ruby-lang.org/issues/10450">#10450</a>)</p>
<p>Attached is a patch that does the necessary change.</p>