https://bugs.ruby-lang.org/
https://bugs.ruby-lang.org/favicon.ico?1711330511
2016-02-07T20:53:55Z
Ruby Issue Tracking System
Ruby master - Feature #12057: Allow methods with `yield` to be called without a block
https://bugs.ruby-lang.org/issues/12057?journal_id=56922
2016-02-07T20:53:55Z
alexeymuranov (Alexey Muranov)
<ul></ul><p>Or maybe not an iterator but a delimited continuation?</p>
<p>Probably the following behavior is more natural:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">f</span>
<span class="p">[</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'b'</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">].</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">c</span><span class="o">|</span>
<span class="nb">puts</span> <span class="k">yield</span> <span class="n">c</span>
<span class="k">end</span>
<span class="k">return</span> <span class="s1">'d'</span>
<span class="k">end</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">f</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : a</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="s2">"(</span><span class="si">#{</span> <span class="n">v</span> <span class="si">}</span><span class="s2">)"</span><span class="p">)</span> <span class="c1"># : (a)</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : b</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="s2">"(</span><span class="si">#{</span> <span class="n">v</span> <span class="si">}</span><span class="s2">)"</span><span class="p">)</span> <span class="c1"># : (b)</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : c</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="s2">"(</span><span class="si">#{</span> <span class="n">v</span> <span class="si">}</span><span class="s2">)"</span><span class="p">)</span> <span class="c1"># : (c)</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : d</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">f</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : a</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="s2">"(</span><span class="si">#{</span> <span class="n">v</span> <span class="si">}</span><span class="s2">)"</span><span class="p">)</span> <span class="p">{</span><span class="o">|</span><span class="n">v</span><span class="o">|</span> <span class="s2">"[</span><span class="si">#{</span> <span class="n">v</span> <span class="si">}</span><span class="s2">]"</span><span class="p">}</span>
<span class="c1"># : (a)</span>
<span class="c1"># [b]</span>
<span class="c1"># [c]</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : d</span>
</code></pre>
<p>So by default "<code>yield</code>" would be just "return-with-current-delimited-continuation", but if a block is given, all references to "<code>yield</code>" in the method would be rebound to run that block.</p>
<p>By analogy to "<code>yield from</code>" in Python 3.3, a method <code>yield_from</code> can be created to work as follows:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">f</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">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="k">yield</span> <span class="n">i</span>
<span class="k">end</span>
<span class="kp">nil</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">g</span>
<span class="n">yield_from</span> <span class="n">f</span>
<span class="k">yield</span> <span class="mi">0</span>
<span class="k">end</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">g</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : 1</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : 2</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : 3</span>
<span class="n">c</span><span class="p">,</span> <span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : 0</span>
<span class="n">v</span> <span class="o">=</span> <span class="n">c</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="s1">'The End'</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">v</span> <span class="c1"># : The End</span>
</code></pre>
<p>"<code>yield_from nil</code>" does nothing.</p>
<p>P.S. It looks like what Python does is a bit more complicated and rather nonlogical (probably searching for "<code>yield</code>" keyword at the definition time).</p>
Ruby master - Feature #12057: Allow methods with `yield` to be called without a block
https://bugs.ruby-lang.org/issues/12057?journal_id=59704
2016-07-20T02:15:29Z
shyouhei (Shyouhei Urabe)
shyouhei@ruby-lang.org
<ul></ul><p>What OP wants can be done using enumerator.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'enumerator'</span>
<span class="k">def</span> <span class="nf">f</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="p">.</span><span class="nf">yield</span> <span class="s1">'a'</span>
<span class="n">y</span><span class="p">.</span><span class="nf">yield</span> <span class="s1">'b'</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">f</span>
<span class="nb">puts</span> <span class="n">e</span><span class="p">.</span><span class="nf">next</span> <span class="c1"># => a</span>
<span class="nb">puts</span> <span class="n">e</span><span class="p">.</span><span class="nf">next</span> <span class="c1"># => b</span>
</code></pre>
<p>Or, I might be failing to understand the request. Might it be "if block is present call it, but if absent no error" request? If so, following one line addition solves such request.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">f</span>
<span class="k">return</span> <span class="n">enum_for</span><span class="p">(</span><span class="n">__method__</span><span class="p">)</span> <span class="k">unless</span> <span class="nb">block_given?</span> <span class="c1"># this</span>
<span class="k">yield</span> <span class="s1">'a'</span>
<span class="k">yield</span> <span class="s1">'b'</span>
<span class="k">end</span>
<span class="n">e</span> <span class="o">=</span> <span class="n">f</span>
<span class="nb">puts</span> <span class="n">e</span><span class="p">.</span><span class="nf">next</span> <span class="c1"># => a</span>
<span class="nb">puts</span> <span class="n">e</span><span class="p">.</span><span class="nf">next</span> <span class="c1"># => b</span>
</code></pre>
<p>Either way, I see no need to extend the language.</p>
Ruby master - Feature #12057: Allow methods with `yield` to be called without a block
https://bugs.ruby-lang.org/issues/12057?journal_id=95595
2021-12-23T23:43:59Z
hsbt (Hiroshi SHIBATA)
hsbt@ruby-lang.org
<ul><li><strong>Project</strong> changed from <i>14</i> to <i>Ruby master</i></li></ul>