https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112020-01-10T22:36:38ZRuby Issue Tracking SystemRuby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=837632020-01-10T22:36:38ZEregon (Benoit Daloze)
<ul><li><strong>Related to</strong> <i><a class="issue tracker-2 status-5 priority-4 priority-default closed" href="/issues/15973">Feature #15973</a>: Let Kernel#lambda always return a lambda</i> added</li></ul> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=837872020-01-11T22:44:24Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul></ul><blockquote>
<p>I believe exactly 0 people want foo { return 42 } to change its meaning based on whether foo calls define_method or not.</p>
</blockquote>
<p>This is wrong, there is at least me 😅</p>
<p>I believe that many API use <code>define_method</code> for metaprogramming and allow <code>return</code> within their blocks.</p>
<p>One example is RSpec's <code>let</code>:</p>
<pre><code> RSpec.describe Something do
let(:foo) { return 42 }
end
</code></pre>
<p>It is 100% clear what is meant and there are gazillions <code>let</code> blocks in the wild. This is just one example.</p>
<p>This would be a compatibility nightmare, for a gain I can not see (here simply raising an error).</p>
<p>I am strongly against this.</p> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=837972020-01-12T14:20:06Zzverok (Victor Shepelev)zverok.offline@gmail.com
<ul></ul><p><a class="user active user-mention" href="https://redmine.ruby-lang.org/users/772">@Eregon (Benoit Daloze)</a> what is the exact proposal of this ticket? I am not sure neither from title nor from description :(</p>
<p>As a side note, in regards to the last part:</p>
<blockquote>
<p>They might also look at proc.parameters which gives <code>[[:opt, :a], [:opt, :b]]</code> which does not differentiate a and b even though only b has a proper default value.<br>
<code>lambda { |a,b=1| }.parameters</code> returns the more useful <code>[[:req, :a], [:opt, :b]]</code>.</p>
</blockquote>
<blockquote>
<p>Maybe we should return the same as for a lambda for non_lambda.parameters?</p>
</blockquote>
<p>I believe curent behavior is pretty consistent, as it describes what it would realy accept. <code>req</code> means it will raise "Wrong number of arguments" if the argument is not provided, <code>opt</code> means it will accept argument's absence and will provide the default value. So, <code>proc { |a, b=1|</code> "real" signature (considering how it will process its args), is in fact <code>proc { |a=nil, b=1, *|</code>. <strong>If</strong> some complicated code accepts "any callable" and somehow validates "what args it requires", <code>opt</code> is more true for non-lambda's arg than <code>req</code>.</p> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=837982020-01-12T16:19:35ZEregon (Benoit Daloze)
<ul></ul><p>marcandre (Marc-Andre Lafortune) wrote:</p>
<blockquote>
<p>One example is RSpec's <code>let</code>:</p>
</blockquote>
<p>I guess we'll have to disagree on that one, I think the code below should return from the surrounding method/file.</p>
<blockquote>
<pre><code> RSpec.describe Something do
let(:foo) { return 42 }
end
</code></pre>
</blockquote>
<blockquote>
<p>It is 100% clear what is meant and there are gazillions <code>let</code> blocks in the wild. This is just one example.</p>
</blockquote>
<p>I would think very few <code>let</code> use <code>return</code> though, do you have a real world example?</p>
<blockquote>
<p>This would be a compatibility nightmare, for a gain I can not see (here simply raising an error).</p>
</blockquote>
<p>If we do the approach where we just wrap the non-lambda Proc in a lambda automatically it would be compatible for that case.</p> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=837992020-01-12T16:24:32ZEregon (Benoit Daloze)
<ul></ul><p>zverok (Victor Shepelev) wrote:</p>
<blockquote>
<p>I believe curent behavior is pretty consistent, as it describes what it would realy accept.</p>
</blockquote>
<p>Yes, in that regard it's inconsistent.<br>
It might be impractical though, depending on whether you want something that reflects what the user writes (i.e., I'd argue always unexpected for the user to be called with 0 arguments) or how many arguments the method accepts.</p>
<p>But anyway <code>Proc#arity</code> is clearly inconsistent with <code>parameters</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="nb">proc</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">1</span><span class="o">|</span> <span class="p">}.</span><span class="nf">arity</span>
<span class="o">=></span> <span class="mi">1</span> <span class="c1"># => should be -1, accepts any amount of arguments</span>
<span class="o">></span> <span class="nb">lambda</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">1</span><span class="o">|</span> <span class="p">}.</span><span class="nf">arity</span>
<span class="o">=></span> <span class="o">-</span><span class="mi">2</span>
<span class="no">In</span> <span class="n">contrast</span> <span class="ss">to:
</span><span class="o">></span> <span class="nb">proc</span> <span class="p">{</span> <span class="o">|*</span><span class="n">rest</span><span class="o">|</span> <span class="p">}.</span><span class="nf">arity</span>
<span class="o">=></span> <span class="o">-</span><span class="mi">1</span> <span class="c1"># OK</span>
<span class="o">></span> <span class="nb">lambda</span> <span class="p">{</span> <span class="o">|*</span><span class="n">rest</span><span class="o">|</span> <span class="p">}.</span><span class="nf">arity</span>
<span class="o">=></span> <span class="o">-</span><span class="mi">1</span> <span class="c1"># OK</span>
</code></pre>
<p>And I'd argue <code>Proc#arity</code> is what should be used to know how many arguments are required and allowed, not <code>Proc#parameters</code>.</p> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=838002020-01-12T16:27:33ZEregon (Benoit Daloze)
<ul></ul><p>Eregon (Benoit Daloze) wrote:</p>
<blockquote>
<p>If we do the approach where we just wrap the non-lambda Proc in a lambda automatically it would be compatible for that case.</p>
</blockquote>
<p>I'm tired, that's wrong, it would actually return from the file, just like any other non-lambda block.<br>
That would be consistent, but yet it would be incompatible for those cases with <code>return</code> inside a <code>block</code> given to <code>define_method</code> later on.<br>
I think those cases are very rare though.</p> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=838622020-01-14T13:19:11ZEregon (Benoit Daloze)
<ul><li><strong>Subject</strong> changed from <i>define_method(non_lambda) should not the semantics of the given Proc</i> to <i>define_method(non_lambda) should not change the semantics of the given Proc</i></li></ul> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=838642020-01-14T13:19:27ZEregon (Benoit Daloze)
<ul><li><strong>Related to</strong> <i><a class="issue tracker-2 status-5 priority-4 priority-default closed" href="/issues/15357">Feature #15357</a>: Proc#parameters returns incomplete type information</i> added</li></ul> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=839182020-01-16T08:18:01Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Rejected</i></li></ul><p>There could be enormous code breakages by the proposed change. The compatibility is more important than slightly better consistency.</p>
<p>Matz.</p> Ruby master - Feature #16499: define_method(non_lambda) should not change the semantics of the given Prochttps://redmine.ruby-lang.org/issues/16499?journal_id=839262020-01-16T09:57:30Zlarskanis (Lars Kanis)
<ul></ul><p>Unfortunately <code>define_method</code> is currently the only way to retrieve <code>Proc#parameters</code> without information loss. See <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Proc#parameters returns incomplete type information (Closed)" href="https://redmine.ruby-lang.org/issues/15357">#15357</a> and <a href="https://github.com/larskanis/eventbox/blob/3bcbc30096c6003e96d41c6496c781dfc90ac36a/lib/eventbox/argument_wrapper.rb#L10-L17" class="external">here</a> for the workaround per <code>default_method</code>. Therefore fixing <code>default_method</code> would also require fixing <code>Proc#parameters</code>.</p>