https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112015-12-07T03:52:16ZRuby Issue Tracking SystemRuby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=552652015-12-07T03:52:16Zbughit (bug hit)
<ul><li><strong>Subject</strong> changed from <i>Mudule#using does not make sense as a method</i> to <i>Module#using does not make sense as a method</i></li></ul> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=552712015-12-07T06:52:02Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Feedback</i></li></ul><p>Can elaborate what do you want if <code>using</code> should not be a method.<br>
Considering a new keyword would break existing code, I don't think it's a good idea.</p>
<p>Matz.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553182015-12-07T16:09:55Zbughit (bug hit)
<ul></ul><p>Yukihiro Matsumoto wrote:</p>
<blockquote>
<p>Can elaborate what do you want if <code>using</code> should not be a method.<br>
Considering a new keyword would break existing code, I don't think it's a good idea.</p>
</blockquote>
<p>I don't know what possibilities there are, it just struck me that it was not behaving at all as a method, methods affect their dynamically scoped receiver, <code>using</code> affects the lexically scoped currently open module. So a keyword, if it were possible, would be more appropriate. Don't know what else it could be.</p>
<p>If it stays a method, what about #3</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Bar</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">refined?</span>
<span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span>
<span class="k">end</span>
<span class="no">Foo</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Refinement</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>what should happen here?</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553192015-12-07T17:00:48Zmatz (Yukihiro Matsumoto)matz@ruby.or.jp
<ul></ul><p>Providing a feature by a method does not imply dynamic scoping, for example, Module#private etc. work in lexical scope.</p>
<p>Matz.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553232015-12-07T17:21:42Zbughit (bug hit)
<ul></ul><p>Yukihiro Matsumoto wrote:</p>
<blockquote>
<p>Providing a feature by a method does not imply dynamic scoping, for example, Module#private etc. work in lexical scope.</p>
<p>Matz.</p>
</blockquote>
<p>Well, since it's an established pattern, one has to just accept it. It does seem unintuitive to me that method calls, which are dynamically bound to self, are actually operating on the currently open class</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553242015-12-07T17:43:29Zbughit (bug hit)
<ul></ul><p>Yukihiro Matsumoto wrote:</p>
<blockquote>
<p>Providing a feature by a method does not imply dynamic scoping, for example, Module#private etc. work in lexical scope.</p>
<p>Matz.</p>
</blockquote>
<p>actually <code>private</code> is more dynamic than <code>using</code>, here's an example of private working not on the currently open class but on the dynamically bound default definee:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Class1</span><span class="p">.</span><span class="nf">class_eval</span> <span class="k">do</span>
<span class="kp">private</span>
<span class="k">def</span> <span class="nf">meth1</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Class1</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">meth1</span> <span class="c1"># private method `meth1' called</span>
</code></pre>
<p>whereas using is not affected by <code>self</code> or "default definee"</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Refinement</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">refined?</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Foo</span>
<span class="c1">#using Refinement</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">refined?</span>
<span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Foo</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Refinement</span>
<span class="nb">p</span> <span class="n">refined?</span> <span class="c1"># false</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="no">Foo</span><span class="p">.</span><span class="nf">refined?</span> <span class="c1">#false</span>
</code></pre>
<p>Is the above behavior correct? Instead of doing nothing, should this use of <code>using</code> produce an error or perhaps work inside the <code>module_eval</code> block</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553722015-12-09T01:17:26Zshugo (Shugo Maeda)
<ul></ul><p>Yukihiro Matsumoto wrote:</p>
<blockquote>
<p>Providing a feature by a method does not imply dynamic scoping, for example, Module#private etc. work in lexical scope.</p>
</blockquote>
<p>However, it might be better to provide Kernel#using instead of main.using and Module#using,<br>
because the behavior does not depend on the receiver.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553732015-12-09T01:31:58Zbughit (bug hit)
<ul></ul><p>Please explain the following behavior of <code>using</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Refinement</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">refined?</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Foo</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">refined?</span>
<span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Foo</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Refinement</span>
<span class="nb">p</span> <span class="n">refined?</span> <span class="c1"># false</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="no">Foo</span><span class="p">.</span><span class="nf">refined?</span> <span class="c1">#false</span>
</code></pre>
<p>If this is a noop, as it seems to be, then it should not be allowed</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553742015-12-09T01:41:42Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>It is not a noop, just you don't use the refined method there.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553752015-12-09T01:51:02Zbughit (bug hit)
<ul></ul><p>Nobuyoshi Nakada wrote:</p>
<blockquote>
<p>It is not a noop, just you don't use the refined method there.</p>
</blockquote>
<p>Where "there"? Where should I use the refined method to see the effect of that using call?</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553762015-12-09T01:55:16Zbughit (bug hit)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<p>Nobuyoshi Nakada wrote:</p>
<blockquote>
<p>It is not a noop, just you don't use the refined method there.</p>
</blockquote>
<p>Where "there"? Where should I use the refined method to see the effect of that using call?</p>
</blockquote>
<p>ok got it, thanks</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Refinement</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">refined?</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Foo</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">refined?</span>
<span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Foo</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Refinement</span>
<span class="nb">p</span><span class="p">((</span><span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span><span class="p">))</span> <span class="c1">#true</span>
<span class="k">end</span>
</code></pre> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553772015-12-09T02:00:12Zbughit (bug hit)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<p>Nobuyoshi Nakada wrote:</p>
<blockquote>
<p>It is not a noop, just you don't use the refined method there.</p>
</blockquote>
<p>Where "there"? Where should I use the refined method to see the effect of that using call?</p>
</blockquote>
<p>ok got it, thanks</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Refinement</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">refined?</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Foo</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">refined?</span>
<span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Foo</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Refinement</span>
<span class="nb">p</span><span class="p">((</span><span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span><span class="p">))</span> <span class="c1">#true</span>
<span class="k">end</span>
</code></pre>
</blockquote>
<p>so if <code>using</code> inside module_eval is intended to work, then invoking such a module_eval from a method should also work (it raises Module#using is not permitted in methods):</p>
<pre><code class="Ruby syntaxhl" data-language="Ruby"><span class="k">module</span> <span class="nn">Refinement</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">refined?</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Foo</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">foo</span>
<span class="nb">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Refinement</span> <span class="c1"># Module#using is not permitted in methods</span>
<span class="nb">p</span><span class="p">((</span><span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span><span class="p">))</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">foo</span>
<span class="k">end</span>
</code></pre> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553802015-12-09T05:02:35Zshugo (Shugo Maeda)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<p>so if <code>using</code> inside module_eval is intended to work, then invoking such a module_eval from a method should also work (it raises Module#using is not permitted in methods):</p>
</blockquote>
<p>Module#using is not intented to work as you expect.</p>
<p>Instead, the following extension of *_eval might be considerable:</p>
<pre><code> module_eval(using: Refinement) {
...
}
</code></pre> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553832015-12-09T05:17:17Zbughit (bug hit)
<ul></ul><p>Shugo Maeda wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<p>so if <code>using</code> inside module_eval is intended to work, then invoking such a module_eval from a method should also work (it raises Module#using is not permitted in methods):</p>
</blockquote>
<p>Module#using is not intented to work as you expect.</p>
</blockquote>
<p>This wasn't really my expectation, it was nobu's explanation (It is not a noop, just you don't use the refined method there), which I confirmed.</p>
<p>"using" called from a module_eval block activates the refinement in the block</p>
<p>Are you saying that's a bug?</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553842015-12-09T05:29:29Zshugo (Shugo Maeda)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<p>Shugo Maeda wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<p>so if <code>using</code> inside module_eval is intended to work, then invoking such a module_eval from a method should also work (it raises Module#using is not permitted in methods):</p>
</blockquote>
<p>Module#using is not intented to work as you expect.</p>
</blockquote>
<p>This wasn't really my expectation, it was nobu's explanation (It is not a noop, just you don't use the refined method there), which I confirmed.</p>
<p>"using" called from a module_eval block activates the refinement in the block</p>
<p>Are you saying that's a bug?</p>
</blockquote>
<p>Nobu didn't explain that Module#using should work in methods.<br>
Module#using is designed not for such dynamic use.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553892015-12-09T05:40:13Zbughit (bug hit)
<ul></ul><p>Shugo Maeda wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<p>Shugo Maeda wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<p>so if <code>using</code> inside module_eval is intended to work, then invoking such a module_eval from a method should also work (it raises Module#using is not permitted in methods):</p>
</blockquote>
<p>Module#using is not intented to work as you expect.</p>
</blockquote>
<p>This wasn't really my expectation, it was nobu's explanation (It is not a noop, just you don't use the refined method there), which I confirmed.</p>
<p>"using" called from a module_eval block activates the refinement in the block</p>
<p>Are you saying that's a bug?</p>
</blockquote>
<p>Nobu didn't explain that Module#using should work in methods.<br>
Module#using is designed not for such dynamic use.</p>
</blockquote>
<p>Note that when #using is called in a module_eval block, its effect is confined to the body of the block. So why should it matter if module_eval is called from a method or top level or from another module/class? <del>Regardless of where it's called, #using inside it works the same.</del> The call site does not influence what #using does nor is influenced by it.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=553942015-12-09T06:24:26Zshugo (Shugo Maeda)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<blockquote>
<p>Nobu didn't explain that Module#using should work in methods.<br>
Module#using is designed not for such dynamic use.</p>
</blockquote>
<p>Note that when #using is called in a module_eval block, its effect is confined to the body of the block. So why should it matter if module_eval is called from a method or top level or from another module/class? <del>Regardless of where it's called, #using inside it works the same.</del> The call site does not influence what #using does nor is influenced by it.</p>
</blockquote>
<p>Because refinement activation should be as static as possible.<br>
It might be better to prohibit Module#using in module_eval.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554132015-12-09T16:37:42Zbughit (bug hit)
<ul></ul><p>Shugo Maeda wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<blockquote>
<p>Nobu didn't explain that Module#using should work in methods.<br>
Module#using is designed not for such dynamic use.</p>
</blockquote>
<p>Note that when #using is called in a module_eval block, its effect is confined to the body of the block. So why should it matter if module_eval is called from a method or top level or from another module/class? <del>Regardless of where it's called, #using inside it works the same.</del> The call site does not influence what #using does nor is influenced by it.</p>
</blockquote>
<p>Because refinement activation should be as static as possible.<br>
It might be better to prohibit Module#using in module_eval.</p>
</blockquote>
<p>Perhaps, since you can apply the refinement outside the module_eval block which will also affect the block:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Refinement</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">refined?</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Foo</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Bar</span>
<span class="n">using</span> <span class="no">Refinement</span>
<span class="no">Foo</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="nb">p</span><span class="p">((</span><span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span><span class="p">))</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>so a #using in module_eval is only useful if you want the refinement confined to the block. There might be uses for that, not sure.</p>
<p>But if this functionality remains, it should work wherever module_eval is invoked.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554312015-12-10T03:58:44Zshugo (Shugo Maeda)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<p>so a #using in module_eval is only useful if you want the refinement confined to the block. There might be uses for that, not sure.</p>
</blockquote>
<p>Yes, it's the current intended behavior.</p>
<blockquote>
<p>But if this functionality remains, it should work wherever module_eval is invoked.</p>
</blockquote>
<p>Such dynamic extension of refinements should be discussed in a different ticket as a new feature.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554362015-12-10T07:01:57Zbughit (bug hit)
<ul></ul><p>Shugo Maeda wrote:</p>
<blockquote>
<p>...<br>
Because refinement activation should be as static as possible.<br>
...</p>
</blockquote>
<p>ruby is too dynamic a language to have a clear distinction between what you're calling "static" and "dynamic" You are labeling class bodies as "static" and methods "dynamic" but a class body is executable ruby and can be invoked by methods, so the current restriction on module_eval can be overcome with relative ease:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Refinement</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">refined?</span>
<span class="kp">true</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Foo</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Bar</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">mod_eval_with_refine</span><span class="p">(</span><span class="n">mod</span><span class="p">)</span>
<span class="n">singleton_class</span><span class="p">.</span><span class="nf">instance_variable_set</span> <span class="ss">:@mod</span><span class="p">,</span> <span class="n">mod</span>
<span class="k">class</span> <span class="o"><<</span> <span class="nb">self</span>
<span class="vi">@mod</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Refinement</span>
<span class="nb">p</span><span class="p">((</span><span class="s1">''</span><span class="p">.</span><span class="nf">refined?</span> <span class="k">rescue</span> <span class="kp">false</span><span class="p">))</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Bar</span><span class="p">.</span><span class="nf">mod_eval_with_refine</span><span class="p">(</span><span class="no">Foo</span><span class="p">)</span>
</code></pre> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554372015-12-10T07:07:21Zshugo (Shugo Maeda)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<p>Shugo Maeda wrote:</p>
<blockquote>
<p>...<br>
Because refinement activation should be as static as possible.<br>
...</p>
</blockquote>
<p>ruby is too dynamic a language to have a clear distinction between what you're calling "static" and "dynamic" You are labeling class bodies as "static" and methods "dynamic" but a class body is executable ruby and can be invoked by methods, so the current restriction on module_eval can be overcome with relative ease:</p>
</blockquote>
<p>Methods are expected to be invoked more than once, so there's a significant difference from class bodies.<br>
That's why static features like constant assignments are prohibited in method definitions.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554382015-12-10T07:17:20Zbughit (bug hit)
<ul></ul><p>Shugo Maeda wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<p>Shugo Maeda wrote:</p>
<blockquote>
<p>...<br>
Because refinement activation should be as static as possible.<br>
...</p>
</blockquote>
<p>ruby is too dynamic a language to have a clear distinction between what you're calling "static" and "dynamic" You are labeling class bodies as "static" and methods "dynamic" but a class body is executable ruby and can be invoked by methods, so the current restriction on module_eval can be overcome with relative ease:</p>
</blockquote>
<p>Methods are expected to be invoked more than once, so there's a significant difference from class bodies.<br>
That's why static features like constant assignments are prohibited in method definitions.</p>
</blockquote>
<p>Did you see the example in my previous post? Effectively there is no prohibition against module_eval with #using in methods, because you can open a class in a method and call module_eval from there.</p>
<p>Also you are forgetting a category of methods (class macros) that help initialize/modify classes through meta-programming and are meant to be called once in the class body. Such methods should be able to do whatever the class body can do.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554392015-12-10T09:28:59Zshugo (Shugo Maeda)
<ul></ul><p>bug hit wrote:</p>
<blockquote>
<blockquote>
<blockquote>
<p>ruby is too dynamic a language to have a clear distinction between what you're calling "static" and "dynamic" You are labeling class bodies as "static" and methods "dynamic" but a class body is executable ruby and can be invoked by methods, so the current restriction on module_eval can be overcome with relative ease:</p>
</blockquote>
<p>Methods are expected to be invoked more than once, so there's a significant difference from class bodies.<br>
That's why static features like constant assignments are prohibited in method definitions.</p>
</blockquote>
<p>Did you see the example in my previous post? Effectively there is no prohibition against module_eval with #using in methods, because you can open a class in a method and call module_eval from there.</p>
</blockquote>
<p>Other features have similar loopholes (e.g., constants can be assigned in methods by eval,<br>
private methods can be called by Kernel#send, etc.), but it doesn't mean such restriction<br>
is meaningless, because it can express the intention.</p>
<blockquote>
<p>Also you are forgetting a category of methods (class macros) that help initialize/modify classes through meta-programming and are meant to be called once in the class body. Such methods should be able to do whatever the class body can do.</p>
</blockquote>
<p>Perhaps, perhaps not. I depends on what the phrase "whatever the class body can do" mean.<br>
For exmaple, such methods should be able to define constants in a class, but need not to<br>
be able to define constants in the same way as in a class body.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554462015-12-10T16:12:31Zbughit (bug hit)
<ul></ul><p>Shugo Maeda wrote:</p>
<blockquote>
<p>bug hit wrote:</p>
<blockquote>
<blockquote>
<blockquote>
<p>ruby is too dynamic a language to have a clear distinction between what you're calling "static" and "dynamic" You are labeling class bodies as "static" and methods "dynamic" but a class body is executable ruby and can be invoked by methods, so the current restriction on module_eval can be overcome with relative ease:</p>
</blockquote>
<p>Methods are expected to be invoked more than once, so there's a significant difference from class bodies.<br>
That's why static features like constant assignments are prohibited in method definitions.</p>
</blockquote>
<p>Did you see the example in my previous post? Effectively there is no prohibition against module_eval with #using in methods, because you can open a class in a method and call module_eval from there.</p>
</blockquote>
<p>Other features have similar loopholes (e.g., constants can be assigned in methods by eval,<br>
private methods can be called by Kernel#send, etc.), but it doesn't mean such restriction<br>
is meaningless, because it can express the intention.</p>
<blockquote>
<p>Also you are forgetting a category of methods (class macros) that help initialize/modify classes through meta-programming and are meant to be called once in the class body. Such methods should be able to do whatever the class body can do.</p>
</blockquote>
<p>Perhaps, perhaps not. I depends on what the phrase "whatever the class body can do" mean.<br>
For exmaple, such methods should be able to define constants in a class, but need not to<br>
be able to define constants in the same way as in a class body.</p>
</blockquote>
<p>Of course I don't mean in the same exact way, meta-programming is different than native syntax. However the question of "how" does not apply here, because you are arguing that it should be forbidden (not different), and I'm saying that if a class body can call a module_eval with using, then a class macro method should be able to, as well.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554862015-12-12T04:35:54Zshugo (Shugo Maeda)
<ul><li><strong>Assignee</strong> set to <i>matz (Yukihiro Matsumoto)</i></li></ul><p>bug hit wrote:</p>
<blockquote>
<blockquote>
<p>Perhaps, perhaps not. I depends on what the phrase "whatever the class body can do" mean.<br>
For exmaple, such methods should be able to define constants in a class, but need not to<br>
be able to define constants in the same way as in a class body.</p>
</blockquote>
<p>Of course I don't mean in the same exact way, meta-programming is different than native syntax. However the question of "how" does not apply here, because you are arguing that it should be forbidden (not different), and I'm saying that if a class body can call a module_eval with using, then a class macro method should be able to, as well.</p>
</blockquote>
<p>As I stated before, it might be better to introduce Kernel#using, which ignores module_eval blocks as constant lookup do.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Foo</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">foo</span>
<span class="nb">puts</span> <span class="s2">"foo"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Bar</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">Baz</span>
<span class="no">Bar</span><span class="p">.</span><span class="nf">module_eval</span> <span class="k">do</span>
<span class="n">using</span> <span class="no">Foo</span>
<span class="s2">""</span><span class="p">.</span><span class="nf">foo</span> <span class="c1">#=> foo</span>
<span class="k">end</span>
<span class="s2">""</span><span class="p">.</span><span class="nf">foo</span> <span class="c1">#=> foo</span>
<span class="k">end</span>
<span class="s2">""</span><span class="p">.</span><span class="nf">foo</span> <span class="c1">#=> error</span>
</code></pre>
<p>I'd like to hear Matz's opinion.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=554882015-12-12T06:06:44Zshugo (Shugo Maeda)
<ul></ul><p>Shugo Maeda wrote:</p>
<blockquote>
<p>As I stated before, it might be better to introduce Kernel#using, which ignores module_eval blocks as constant lookup do.</p>
</blockquote>
<p>Or it might be better to prohibit using in blocks.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=656832017-07-07T17:07:31Zbughit (bug hit)
<ul></ul><p>matz (Yukihiro Matsumoto) wrote:</p>
<blockquote>
<p>Providing a feature by a method does not imply dynamic scoping, for example, Module#private etc. work in lexical scope.</p>
</blockquote>
<p>I didn't think about Module#private too deeply at the time, but recently was prompted by something, and Module#private is not lexical</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Mod1</span>
<span class="k">class</span> <span class="nc">Class1</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">lookup_class</span>
<span class="no">Class1</span>
<span class="k">end</span>
<span class="n">lookup_class</span><span class="p">.</span><span class="nf">class_eval</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">foo1</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="kp">private</span>
<span class="k">def</span> <span class="nf">foo2</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">lookup_class</span><span class="p">.</span><span class="nf">instance_eval</span> <span class="k">do</span>
<span class="n">define_method</span> <span class="ss">:bar1</span> <span class="k">do</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">bar1</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="kp">private</span>
<span class="k">def</span> <span class="nf">bar2</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="n">define_method</span> <span class="ss">:bar2</span> <span class="k">do</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">c1</span> <span class="o">=</span> <span class="no">Class1</span><span class="p">.</span><span class="nf">new</span>
<span class="n">c1</span><span class="p">.</span><span class="nf">foo1</span><span class="p">.</span><span class="nf">foo2</span> <span class="k">rescue</span> <span class="nb">puts</span> <span class="vg">$!</span><span class="p">.</span><span class="nf">inspect</span>
<span class="no">Class1</span><span class="p">.</span><span class="nf">bar1</span><span class="p">.</span><span class="nf">bar2</span> <span class="k">rescue</span> <span class="nb">puts</span> <span class="vg">$!</span><span class="p">.</span><span class="nf">inspect</span>
<span class="n">c1</span><span class="p">.</span><span class="nf">bar1</span><span class="p">.</span><span class="nf">bar2</span> <span class="k">rescue</span> <span class="nb">puts</span> <span class="vg">$!</span><span class="p">.</span><span class="nf">inspect</span>
<span class="k">end</span>
</code></pre>
<p>it affects the dynamically scoped default definee, which though dynamic does not necessarily match the receiver.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=656882017-07-08T02:10:25Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<ul></ul><p>Seems that your "dynamic" and "lexical" words differ from ours.</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=656912017-07-08T03:28:49Zbughit (bug hit)
<ul></ul><p>nobu (Nobuyoshi Nakada) wrote:</p>
<blockquote>
<p>Seems that your "dynamic" and "lexical" words differ from ours.</p>
</blockquote>
<p>I was using "dynamic" to mean that its dynamically "bound" (applies) to the default definee at the point of invocation, not the lexically determined currently open class. It's true that the receiver does not matter at all (I initially thought it had to self):</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Mod1</span>
<span class="k">class</span> <span class="nc">Class1</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">lookup_class</span>
<span class="no">Class1</span>
<span class="k">end</span>
<span class="n">lookup_class</span><span class="p">.</span><span class="nf">class_eval</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">foo1</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="no">Module</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:private</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">foo2</span>
<span class="nb">self</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">c1</span> <span class="o">=</span> <span class="no">Class1</span><span class="p">.</span><span class="nf">new</span>
<span class="n">c1</span><span class="p">.</span><span class="nf">foo1</span><span class="p">.</span><span class="nf">foo2</span> <span class="k">rescue</span> <span class="nb">puts</span> <span class="vg">$!</span><span class="p">.</span><span class="nf">inspect</span>
<span class="k">end</span>
</code></pre>
<p>Please clarify how you're using dynamic vs lexical?</p> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=716582018-04-26T11:05:20ZAlexWayfer (Alexander Popov)alex.wayfer@gmail.com
<ul></ul><p>From RSpec:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">let</span><span class="p">(</span><span class="ss">:test_class</span><span class="p">)</span> <span class="k">do</span>
<span class="no">Class</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">described_class</span><span class="p">)</span> <span class="k">do</span>
<span class="kp">private</span>
<span class="n">using</span> <span class="no">SomeRefiningModule</span> <span class="c1"># => RuntimeError: Module#using is not permitted in methods</span>
<span class="k">def</span> <span class="nf">foo</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre> Ruby master - Bug #11779: Module#using does not make sense as a methodhttps://bugs.ruby-lang.org/issues/11779?journal_id=925622021-06-17T09:58:59ZEregon (Benoit Daloze)
<ul></ul><p><code>Module#using</code> has a granularity of "constant lexical scope", i.e., a scope that is only changed by <code>module</code> or <code>class</code> keywords.</p>
<p>Maybe the docs should be improved in this regard?</p>
<p>Current docs say this</p>
<pre><code>Import class refinements from module into the current class
or module definition.
</code></pre>
<p>which seem fair enough but could be more precise (i.e., only for <code>module</code> or <code>class</code> keywords, not for module_eval/module_exec/etc).</p>