https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112021-05-05T22:28:16ZRuby Issue Tracking SystemRuby master - Feature #17844: Support list of methods to test with respond_to?https://bugs.ruby-lang.org/issues/17844?journal_id=918572021-05-05T22:28:16Zmatheusrich (Matheus Richard)matheusrichardt@gmail.com
<ul></ul><p>I would be confused whether it should respond to ALL of the params, or just ANY of them. It could be just me, though.</p>
<p>Maybe adding a <code>respond_to_any?</code> would solve that.</p> Ruby master - Feature #17844: Support list of methods to test with respond_to?https://bugs.ruby-lang.org/issues/17844?journal_id=918592021-05-06T07:22:26Zsvoop (Sven Schwyn)svoop_he38hj327c@delirium.ch
<ul></ul><p>Fair point, but I don't think <code>respond_to_any?</code> is a real use case given <code>respond_to?</code> is mostly used to check whether an object implements the necessary interface: The information "it implements method1 OR method2" has little practical value.</p>
<p>Also, the predominant assumption made by other methods accepting one or many args appears to be AND (additive):</p>
<ul>
<li><code>Array#push</code></li>
<li><code>Array#union</code></li>
<li><code>Hash#slice</code></li>
<li>(many more)</li>
</ul>
<p>TL;DR It should not be a surprise for <code>respond_to?(:email, :name)</code> to returns <code>true</code> if and only if both methods are implemented on the receiver.</p> Ruby master - Feature #17844: Support list of methods to test with respond_to?https://bugs.ruby-lang.org/issues/17844?journal_id=918612021-05-06T08:05:56Zbyroot (Jean Boussier)byroot@ruby-lang.org
<ul></ul><p>Currently the method signature is <code>respond_to?(symbol, include_all=false)</code>, so changing it to what you suggest might break backward compatibility. e.g.:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">>></span> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="ss">:puts</span><span class="p">,</span> <span class="ss">:bar</span><span class="p">)</span>
<span class="o">=></span> <span class="kp">true</span>
</code></pre>
<p>Of course the above is quite a stretch, but I figured it was worth making it clear.</p> Ruby master - Feature #17844: Support list of methods to test with respond_to?https://bugs.ruby-lang.org/issues/17844?journal_id=918622021-05-06T08:18:44Zsvoop (Sven Schwyn)svoop_he38hj327c@delirium.ch
<ul></ul><p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/7941">@byroot (Jean Boussier)</a> You're right, breaking backward compatibility of the signature is out of the question. Not sure for C, but in plain Ruby, it's not a problem:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">just_checkin</span><span class="p">(</span><span class="o">*</span><span class="nb">methods</span><span class="p">,</span> <span class="ss">include_all: </span><span class="kp">false</span><span class="p">)</span>
<span class="nb">puts</span> <span class="nb">methods</span><span class="p">.</span><span class="nf">inspect</span><span class="p">,</span> <span class="n">include_all</span><span class="p">.</span><span class="nf">inspect</span>
<span class="k">end</span>
<span class="n">just_checkin</span><span class="p">(</span><span class="ss">:a</span><span class="p">)</span>
<span class="p">[</span><span class="ss">:a</span><span class="p">]</span>
<span class="kp">false</span>
<span class="n">just_checkin</span><span class="p">(</span><span class="ss">:a</span><span class="p">,</span> <span class="ss">include_all: </span><span class="kp">true</span><span class="p">)</span>
<span class="p">[</span><span class="ss">:a</span><span class="p">]</span>
<span class="kp">true</span>
<span class="n">just_checkin</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="p">[</span><span class="ss">:a</span><span class="p">,</span> <span class="ss">:b</span><span class="p">]</span>
<span class="kp">false</span>
<span class="n">just_checkin</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">include_all: </span><span class="kp">true</span><span class="p">)</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="kp">true</span>
</code></pre>
<p>The alternative (multiple methods must be passed as an Array) for sure don't break anything.</p> Ruby master - Feature #17844: Support list of methods to test with respond_to?https://bugs.ruby-lang.org/issues/17844?journal_id=918662021-05-06T12:17:22Zbyroot (Jean Boussier)byroot@ruby-lang.org
<ul></ul><p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/309">@svoop (Sven Schwyn)</a>, you seem to have missed that <code>include_all</code> is a positional parameter, not a named one.</p> Ruby master - Feature #17844: Support list of methods to test with respond_to?https://bugs.ruby-lang.org/issues/17844?journal_id=918672021-05-06T12:23:13ZEregon (Benoit Daloze)
<ul></ul><p>I think <code>raise ArgumentError unless recipient.respond_to?(:email) && recipient.respond_to?(:name)</code> is good enough.<br>
It's also likely to be significantly faster than <code>recipient.respond_to_all?(:email, :name)</code> since that has variable arguments, would need more complex caching, etc.</p>
<p>I think that pattern is also not frequent enough to deserve such a ad-hoc shortcut.</p>
<p>Or if there are many symbols, you can use <code>%i[email name].all? { recipient.respond_to?(_1) }</code> which is much shorter and clearer than the <code>reduce</code> variant (don't use <code>reduce</code> for that).<br>
That won't be as fast, but it's concise and clear and needs no new API.</p> Ruby master - Feature #17844: Support list of methods to test with respond_to?https://bugs.ruby-lang.org/issues/17844?journal_id=918752021-05-06T19:00:00Zsvoop (Sven Schwyn)svoop_he38hj327c@delirium.ch
<ul></ul><p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/7941">@byroot (Jean Boussier)</a> You're right of course, I'm so tuned in to keyword arguments. :-) Can be done in Ruby as <code>def respond_to?(*args)</code>, but you'd have to check the last args member for type. It might be more ore less ugly in C, I honestly know zilch about C. At least code like <code>if(flag != Qtrue && flag != Qfalse)</code> is already present in the Ruby source.</p>
<p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/772">@Eregon (Benoit Daloze)</a> I like your <code>all?</code> approach a lot, definitely better and more self-explanatory than <code>reduce</code>!</p>