https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112022-12-13T15:18:39ZRuby Issue Tracking SystemRuby master - Bug #19231: Integer#step and Float::INFINITY - inconsistent behaviour when called with and without a blockhttps://bugs.ruby-lang.org/issues/19231?journal_id=1006232022-12-13T15:18:39Zandrykonchin (Andrew Konchin)
<ul><li><strong>Description</strong> updated (<a title="View differences" href="/journals/100623/diff?detail_id=63732">diff</a>)</li></ul> Ruby master - Bug #19231: Integer#step and Float::INFINITY - inconsistent behaviour when called with and without a blockhttps://bugs.ruby-lang.org/issues/19231?journal_id=1006242022-12-13T15:59:29Zmrkn (Kenta Murata)muraken@gmail.com
<ul></ul><p><code>0.step(Float::INFINITY, 10).each</code> generates Float values until Ruby 2.0 and after Ruby 2.6, but it generates Integer values between Ruby 2.1 and 2.5. The reason why the behavior changes after Ruby 2.6 is due to ArithmeticSequence.</p>
<p><code>0.step(Float::INFINITY, 10) { ... }</code> generates Float values until Ruby 2.0, but it generates Integer values after Ruby 2.1.</p>
<p>Hence it's also possible that the right behavior is to generate Integer values rather than Float. We need to know the reason for the behavior change in Ruby 2.1.</p> Ruby master - Bug #19231: Integer#step and Float::INFINITY - inconsistent behaviour when called with and without a blockhttps://bugs.ruby-lang.org/issues/19231?journal_id=1006252022-12-13T18:14:11ZEregon (Benoit Daloze)
<ul></ul><p>IMHO Integer makes sense so one can step by N from 0 to infinity with <code>0.step(Float::INFINITY, 10)</code> (with <code>Numeric#step</code>), since there is no <code>Integer::INFINITY</code>.<br>
Using Float also can cause significant errors with a big enough step or values.</p>
<p>So the rule would be "use floats if <code>receiver</code> or <code>step</code> is Float (ignore <code>to/limit</code>'s type), otherwise leave them as-is.</p>
<p>The keyword form already uses integers for "step infinitely":</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="mi">0</span><span class="p">.</span><span class="nf">step</span><span class="p">(</span><span class="ss">by: </span><span class="mi">10</span><span class="p">).</span><span class="nf">take</span> <span class="mi">2</span>
<span class="o">=></span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">]</span>
<span class="o">></span> <span class="mi">0</span><span class="p">.</span><span class="nf">step</span><span class="p">(</span><span class="ss">by: </span><span class="mi">10</span><span class="p">)</span> <span class="p">{</span> <span class="k">break</span> <span class="n">_1</span> <span class="p">}</span>
<span class="o">=></span> <span class="mi">0</span>
</code></pre>
<p>Probably we need to be consistent with <code>Range#step</code> too:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="p">).</span><span class="nf">step</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="p">{</span> <span class="k">break</span> <span class="n">_1</span> <span class="p">}</span>
<span class="o">=></span> <span class="mi">0</span>
<span class="o">></span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="p">).</span><span class="nf">step</span><span class="p">(</span><span class="mi">10</span><span class="p">).</span><span class="nf">take</span> <span class="mi">2</span>
<span class="o">=></span> <span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">]</span>
<span class="o">></span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="no">Float</span><span class="o">::</span><span class="no">INFINITY</span><span class="p">).</span><span class="nf">step</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="p">{</span> <span class="k">break</span> <span class="n">_1</span> <span class="p">}</span>
<span class="o">=></span> <span class="mf">0.0</span>
<span class="o">></span> <span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="no">Float</span><span class="o">::</span><span class="no">INFINITY</span><span class="p">).</span><span class="nf">step</span><span class="p">(</span><span class="mi">10</span><span class="p">).</span><span class="nf">take</span> <span class="mi">2</span>
<span class="o">=></span> <span class="p">[</span><span class="mf">0.0</span><span class="p">,</span> <span class="mf">10.0</span><span class="p">]</span>
</code></pre> Ruby master - Bug #19231: Integer#step and Float::INFINITY - inconsistent behaviour when called with and without a blockhttps://bugs.ruby-lang.org/issues/19231?journal_id=1049532023-10-18T07:10:24Zkyanagi (Kouhei Yanagita)
<ul></ul><pre><code>% docker run -it --rm rubylang/all-ruby env ALL_RUBY_SINCE=ruby-1.3 ./all-ruby -e 'inf = 1.0/0.0; 0.step(inf, 10) { |x| p x; break }'
ruby-1.3 /tmp/rbFgfjB4:1:in `/': divided by 0 (ZeroDivisionError)
from /tmp/rbFgfjB4:1
exit 1
ruby-1.3.1-990215 0
...
ruby-1.6.8 0
ruby-1.8.0 0.0
...
ruby-2.0.0-p648 0.0
ruby-2.1.0-preview1 0
...
ruby-3.3.0-preview2 0
</code></pre>
<p>The behavior seems to have changed in version 1.8.0 due to <a href="https://github.com/ruby/ruby/commit/936ad40" class="external">https://github.com/ruby/ruby/commit/936ad40</a>.</p>
<p>The behavior seems to have changed in version 2.1.0 due to <a href="https://github.com/ruby/ruby/commit/fd4b5b8" class="external">https://github.com/ruby/ruby/commit/fd4b5b8</a>.<br>
The issue is <a href="https://bugs.ruby-lang.org/issues/8838" class="external">https://bugs.ruby-lang.org/issues/8838</a>.</p>
<p>I think the behavior change in Ruby 1.8.0 was likely not intentional but rather accidental.</p>
<p>I couldn't find any documentation indicating that the behavior change in Ruby 2.1.0 was intentional.<br>
There is no mention in NEWS-2.1.0 either.</p> Ruby master - Bug #19231: Integer#step and Float::INFINITY - inconsistent behaviour when called with and without a blockhttps://bugs.ruby-lang.org/issues/19231?journal_id=1072162024-03-14T05:35:23Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>Weird a little.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">seq</span> <span class="o">=</span> <span class="mi">0</span><span class="p">.</span><span class="nf">step</span><span class="p">(</span><span class="no">Float</span><span class="o">::</span><span class="no">INFINITY</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
<span class="nb">p</span> <span class="n">seq</span><span class="p">.</span><span class="nf">class</span> <span class="c1">#=> Enumerator::ArithmeticSequence</span>
<span class="nb">p</span> <span class="n">seq</span><span class="p">.</span><span class="nf">first</span> <span class="c1">#=> 0</span>
<span class="nb">p</span> <span class="n">seq</span><span class="p">.</span><span class="nf">first</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1">#=> [0.0]</span>
</code></pre> Ruby master - Bug #19231: Integer#step and Float::INFINITY - inconsistent behaviour when called with and without a blockhttps://bugs.ruby-lang.org/issues/19231?journal_id=1072192024-03-14T06:39:29Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p><a href="https://github.com/nobu/ruby/tree/arith_seq-infinite-end" class="external">https://github.com/nobu/ruby/tree/arith_seq-infinite-end</a></p>