Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112020-12-07T05:25:04ZRuby Issue Tracking System
Redmine Ruby master - Bug #17374 (Rejected): Refined methods aren't visible from a refinement's modulehttps://bugs.ruby-lang.org/issues/173742020-12-07T05:25:04Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.caRuby master - Feature #17265 (Feedback): Add `Bool` modulehttps://bugs.ruby-lang.org/issues/172652020-10-19T00:11:59Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>1-line Summary: <code>rbs</code> would benefit from the existence of common ancestor <code>Bool</code> for <code>TrueClass</code> and <code>FalseClass</code>.</p>
<p>Detail:<br>
Matz: I am aware you rejected a similar request, but could we revisit this in light of RBS?</p>
<p>One use case was for an easy way to check for <code>true</code> or <code>false</code> values, instead of simply for truthiness (e.g. for data transfer, strict argument checking, testing, etc.)</p>
<p>I believe there's a new use case: <code>RBS</code></p>
<p>In <code>RBS</code>, the most used types like <code>String</code> and <code>Integer</code> have types for "string-like" and "integer-like" objects: <code>string</code> and <code>integer</code> (all lowercase).</p>
<p>For example the signature for <code>Integer#>></code> is:</p>
<pre><code>def >>: (int) -> Integer
</code></pre>
<p>It accepts an <code>Integer</code> <em>or an object responding to <code>to_int</code></em> (summarized by <code>int</code>) and returns an <code>Integer</code> (and never another class of object responding to <code>to_int</code> or not).</p>
<p>There is a similar idea with boolean values, where a method may accept any object and will use it's truthiness, while returning <code>true | false</code>. For example one of the interface for <code>Enumerable#all?</code> should look like:</p>
<pre><code>def all?: () { (Elem) -> bool } -> true | false
</code></pre>
<p>The user supplied block can return any value, and its truthiness (anything else than <code>nil</code> or <code>false</code>) will be used to determine the result of <code>all?</code>. That result will be <code>true | false</code>, and no other value.</p>
<p>If RBS is to be popular, there will be <em>many</em> signatures for such predicates (in builtin Ruby, stdlib, any gems, applications, etc.). I feel the best option would be <code>Bool</code>, if this would be reflected in Ruby itself.</p>
<p>Proposal: a new global module called <code>Bool</code>, without any method of constant, included in <code>TrueClass</code> and <code>FalseClass</code>.</p>
<p>Following reasons for rejection were given at the time:</p>
<blockquote>
<p>many gems and libraries had already introduced Boolean class. I don't want to break them.</p>
</blockquote>
<p>I looked and found the <a href="https://rubygems.org/gems/bool" class="external"><code>bool</code> gem</a> that defines a <code>Bool</code> module. My proposal is compatible. In any case, this gem looks abandoned, the author Aslak Hellesøy doesn't have the code on github, the gem has had 7000 downloads in the past 6 years and <a href="https://rubygems.org/gems/bool/reverse_dependencies" class="external">has no public reverse dependency</a>. It also fails to install on my machine.</p>
<p>I am not aware of incompatibilities.</p>
<blockquote>
<p><code>true</code> and <code>false</code> are the only representative of true-false values. In Ruby. <code>nil</code> and <code>false</code> are falsy values, and everything else is a true value. There's no meaning for having a superclass of <code>TrueClass</code> and <code>FalseClass</code> as <code>Boolean</code>.</p>
</blockquote>
<p>The proposal is exactly to be able to easily write about this duality of <code>Bool</code> as having only <code>true</code> and <code>false</code> as members, and every Ruby object as being implicitly convertible as being truthy or falsy (<code>bool</code> in RBS).</p>
<p>Discussion in RBS:</p>
<ul>
<li><a href="https://github.com/ruby/rbs/issues/133" class="external">https://github.com/ruby/rbs/issues/133</a></li>
</ul>
<p>Previous feature requests for <code>Boolean</code>:</p>
<ul>
<li><a href="https://bugs.ruby-lang.org/issues/14224" class="external">https://bugs.ruby-lang.org/issues/14224</a></li>
<li><a href="https://bugs.ruby-lang.org/issues/12515" class="external">https://bugs.ruby-lang.org/issues/12515</a></li>
</ul> Ruby master - Bug #17197 (Rejected): Some Hash methods still have arity 2 instead of 1https://bugs.ruby-lang.org/issues/171972020-09-28T02:13:57Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p><code>Hash#each</code> was changed recently to have arity of 1.<br>
All other methods of <code>Hash</code> should behave the same.<br>
Much has been fixed since <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Enumerable & Hash yielding arity (Closed)" href="https://bugs.ruby-lang.org/issues/14015">#14015</a>, but some remains:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Some methods consistently have arity 2:</span>
<span class="p">{</span><span class="ss">a: </span><span class="mi">1</span><span class="p">}.</span><span class="nf">select</span><span class="p">(</span> <span class="o">&-></span><span class="p">(</span><span class="n">_kvp</span><span class="p">)</span> <span class="p">{}</span> <span class="p">)</span> <span class="c1"># => ArgumentError (wrong number of arguments (given 2, expected 1))</span>
</code></pre>
<p>All in all: <code>%i[select keep_if delete_if reject to_h]</code> have their arity still set at 2.</p> Ruby master - Feature #17171 (Rejected): Why is the visibility of constants not affected by `priv...https://bugs.ruby-lang.org/issues/171712020-09-15T20:34:44Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Foo</span>
<span class="k">def</span> <span class="nf">call_me</span>
<span class="c1"># ...</span>
<span class="k">end</span>
<span class="kp">private</span>
<span class="no">SOME_DATA</span> <span class="o">=</span> <span class="sx">%i[...]</span><span class="p">.</span><span class="nf">freeze</span> <span class="c1"># is public, why not private?</span>
<span class="k">def</span> <span class="nf">calc_stuff</span> <span class="c1"># is private, ok.</span>
<span class="c1"># ...</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>It's probably a naive question, but why shouldn't <code>SOME_DATA</code>'s visibility be private?</p>
<p>When writing gems, more often than not the constants that I write are not meant for public consumption. I find it redundant (and tiresome) to explicitly write <code>private_constant :SOME_DATA</code>.</p> Ruby master - Feature #17145 (Rejected): Ractor-aware `Object#deep_freeze`https://bugs.ruby-lang.org/issues/171452020-09-03T18:42:27Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>I'd like to propose <code>Object#deep_freeze</code>:</p>
<p>Freezes recursively the contents of the receiver (by calling <code>deep_freeze</code>) and<br>
then the receiver itself (by calling <code>freeze</code>).<br>
Values that are shareable via <code>Ractor</code> (e.g. classes) are never frozen this way.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># freezes recursively:</span>
<span class="n">ast</span> <span class="o">=</span> <span class="p">[</span><span class="ss">:hash</span><span class="p">,</span> <span class="p">[</span><span class="ss">:pair</span><span class="p">,</span> <span class="p">[</span><span class="ss">:str</span><span class="p">,</span> <span class="s1">'hello'</span><span class="p">],</span> <span class="p">[</span><span class="ss">:sym</span><span class="p">,</span> <span class="ss">:world</span><span class="p">]]].</span><span class="nf">deep_freeze</span>
<span class="n">ast</span><span class="p">.</span><span class="nf">dig</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># => [:str, 'hello']</span>
<span class="n">ast</span><span class="p">.</span><span class="nf">dig</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">).</span><span class="nf">compact!</span> <span class="c1"># => FrozenError</span>
<span class="c1"># does not freeze classes:</span>
<span class="p">[[</span><span class="no">String</span><span class="p">]].</span><span class="nf">deep_freeze</span>
<span class="no">String</span><span class="p">.</span><span class="nf">frozen?</span> <span class="c1"># => false</span>
<span class="c1"># calls `freeze`:</span>
<span class="k">class</span> <span class="nc">Foo</span>
<span class="k">def</span> <span class="nf">freeze</span>
<span class="n">build_cache!</span>
<span class="nb">puts</span> <span class="s2">"Ready for freeze"</span>
<span class="k">super</span>
<span class="k">end</span>
<span class="c1"># ...</span>
<span class="k">end</span>
<span class="p">[[[</span><span class="no">Foo</span><span class="p">.</span><span class="nf">new</span><span class="p">]]].</span><span class="nf">deep_freeze</span> <span class="c1"># => Outputs "Ready for freeze"</span>
</code></pre>
<p>I think a variant <code>deep_freeze!</code> that raises an exception if the result isn't Ractor-shareable would be useful too:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Fire</span>
<span class="k">def</span> <span class="nf">freeze</span>
<span class="c1"># do not call super</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">x</span> <span class="o">=</span> <span class="p">[</span><span class="no">Fire</span><span class="p">.</span><span class="nf">new</span><span class="p">]</span>
<span class="n">x</span><span class="p">.</span><span class="nf">deep_freeze!</span> <span class="c1"># => "Could not be deeply-frozen: #<Fire:0x00007ff151994748>"</span>
</code></pre> Ruby master - Feature #16994 (Feedback): Sets: shorthand for frozen sets of symbols / stringshttps://bugs.ruby-lang.org/issues/169942020-06-26T20:32:22Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>I would like a shorthand syntax for <em>frozen Sets of symbols or of strings</em>.</p>
<p>I am thinking of:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">%</span><span class="n">ws</span><span class="p">{</span><span class="n">hello</span> <span class="n">world</span><span class="p">}</span> <span class="c1"># => Set['hello', 'world'].freeze</span>
<span class="o">%</span><span class="n">is</span><span class="p">{</span><span class="n">hello</span> <span class="n">world</span><span class="p">}</span> <span class="c1"># => Set[:hello, :world].freeze</span>
</code></pre>
<p>The individual strings would be frozen. These literals would be created once at parse time (like Regex are):</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">foo</span>
<span class="nb">p</span> <span class="o">%</span><span class="n">ws</span><span class="p">{</span><span class="n">hello</span> <span class="n">world</span><span class="p">}.</span><span class="nf">object_id</span>
<span class="k">end</span>
<span class="n">foo</span>
<span class="n">foo</span> <span class="c1"># => prints the same id twice</span>
</code></pre>
<p>We should consider these sets to return a unique frozen <code>to_a</code>.</p>
<p>Reminder: Ruby has literal notations for <code>Rational</code> and <code>Complex</code>. I've sadly never had to use either.<br>
I would venture to say that <code>Complex</code> is much less used than <code>Sets</code>, and that sets are underused.</p>
<p>Reminder: previous discussion for builtin syntax was not for frozen literal, strings or symbols specifically: <a href="https://bugs.ruby-lang.org/issues/5478" class="external">https://bugs.ruby-lang.org/issues/5478</a></p>
<p>For builtin notations for generic sets (i.e. <em>unfrozen</em> or containing <em>other than string/symbol</em>), please discuss in another issue.</p> Ruby master - Feature #8840 (Rejected): Yielder#statehttps://bugs.ruby-lang.org/issues/88402013-08-31T07:52:02Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Defining an Enumerator that require a state is currently troublesome. For example, it is not really possible to define an equivalent of Lazy#drop in Ruby without making an assumption on the implementation.</p>
<p>To address this, I propose that we</p>
<p>(a) guarantee that a new Yielder object will be given for each enumeration<br>
(b) add a 'state' attribute to Yielder.</p>
<p>This way, one could implement Lazy#drop in a way similar to:</p>
<p>class Enumerator::Lazy < Enumerator<br>
def drop(n)<br>
n = n.to_i<br>
Lazy.new(self) do |yielder, *values|<br>
yielder.state ||= n<br>
if yielder.state > 0<br>
yielder.state -= 1<br>
else<br>
yielder.yield(*values)<br>
end<br>
end<br>
end<br>
end</p>
<p>Note that (a) is currently true for Ruby MRI, JRuby and Rubinius, but it is not explicit in the documentation.</p> Ruby master - Feature #8026 (Feedback): Need Module#prepended_moduleshttps://bugs.ruby-lang.org/issues/80262013-03-06T12:40:20Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>We should have a way to get the list of prepended modules of a class or module.</p>
<pre><code>module Mixin
end
module Outer
prepend Mixin
end
Mixin.prepended_modules #=> []
Outer.prepended_modules #=> [Mixin]
</code></pre>
<p>See also bug <a class="issue tracker-4 status-5 priority-4 priority-default closed" title="Backport: Module#included_modules includes classes (Closed)" href="https://bugs.ruby-lang.org/issues/8025">#8025</a>.</p> Ruby master - Feature #7299 (Rejected): Ruby should not completely ignore blocks.https://bugs.ruby-lang.org/issues/72992012-11-07T13:06:31Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Ruby should not completely ignore blocks.</p>
<p>const_set :Example, Class.new do<br>
p "Hello, world"<br>
end</p>
<a name="Doesnt-print-anything-generate-any-warning-nor-error"></a>
<h1 >Doesn't print anything, generate any warning nor error.<a href="#Doesnt-print-anything-generate-any-warning-nor-error" class="wiki-anchor">¶</a></h1>
<p>To minimize any impact, Ruby should issue a warning, and in future version could even raise an error.</p>
<p>Even unused variables provide warnings in verbose mode, and they have their use.</p>
<p>I can't think of a case where passing a block to a builtin method that doesn't accept a block is not a programming error though.</p>
<p>If this is approved, I volunteer to implement this.</p> Ruby master - Bug #6538 (Rejected): Mutability of Rational and Complexhttps://bugs.ruby-lang.org/issues/65382012-06-03T07:20:46Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>I hesitated to report this, but there is a "hole" in the immutability of Rational & Complex:</p>
<pre><code>r = Rational(0) # Rationals are immutable
r.freeze # but let's be certain and freeze it!
magic_trick(r) # r is now changed:
r # => (1/42)
</code></pre>
<p>The same thing occurs with Complex. I've left out the definition of <code>magic_trick</code> for anyone who wants to try and figure it out, but it's here: <a href="http://pastie.org/4016117" class="external">http://pastie.org/4016117</a></p>
<p>Is this worth fixing?</p> Ruby master - Bug #6086 (Rejected): Number of arguments and named parametershttps://bugs.ruby-lang.org/issues/60862012-02-25T16:30:57Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>While working on the messages of "wrong number of arguments" error (see <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Treatment of Wrong Number of Arguments (Closed)" href="https://bugs.ruby-lang.org/issues/6085">#6085</a>), I realized that the new named parameter feature can lead to misleading error messages:</p>
<p>def foo(x: 42)<br>
end</p>
<p>arg = {x: :bar}<br>
foo(arg) # => nil (no error)<br>
arg = :bar<br>
foo(arg) # => ArgumentError: wrong number of arguments (1 for 0)</p>
<p>It would be better if the wording was changed for methods accepting options. Maybe something like:</p>
<p>foo(arg) # => ArgumentError: wrong number of arguments (1 for 0 **)</p>
<p>Suggestions?</p> Ruby master - Bug #5228 (Closed): Integer#round fails on some big negative numbershttps://bugs.ruby-lang.org/issues/52282011-08-25T07:50:29Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Integer#round fails for some big negative numbers:</p>
<p>(+25 * 10<strong>70).round(-71) # => 30...00<br>
(-25 * 10</strong>70).round(-71) # => -20...00, should be -30...00</p> Ruby master - Bug #5227 (Closed): Float#round fails on corner caseshttps://bugs.ruby-lang.org/issues/52272011-08-25T06:03:50Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Float#round fails on some corner cases:</p>
<p>42.0.round(300) # => 42.0<br>
42.0.round(308) # => Infinity, should be 42.0<br>
42.0.round(309) # => 42.0</p>
<p>1.0e307.round(1) # => 1.0e307<br>
1.0e307.round(2) # => Infinity, should be 1.0e307</p>
<p>These occur when the exponent of the intermediate value overflows.</p>
<p>The original code already had criteria for extreme values, but we can find much tighter ones, as explained in the patch below. This fixes the bugs above and optimizes for most trivial cases.</p>
<p>I'd be grateful if someone could look it over before I commit it, thanks.</p>
<p>diff --git a/numeric.c b/numeric.c<br>
index 272bbd1..22608c9 100644<br>
--- a/numeric.c<br>
+++ b/numeric.c<br>
@@ -1491,18 +1491,37 @@ flo_round(int argc, VALUE *argv, VALUE num)<br>
VALUE nd;<br>
double number, f;<br>
int ndigits = 0;</p>
<ul>
<li>
<p>int binexp;<br>
long val;</p>
<p>if (argc > 0 && rb_scan_args(argc, argv, "01", &nd) == 1) {<br>
ndigits = NUM2INT(nd);<br>
}<br>
number = RFLOAT_VALUE(num);</p>
</li>
</ul>
<ul>
<li>f = pow(10, abs(ndigits));</li>
<li>
<li>if (isinf(f)) {</li>
<li>
<pre><code> if (ndigits < 0) number = 0;
</code></pre>
</li>
<li>}</li>
<li>else {</li>
</ul>
<ul>
<li>frexp (number , &binexp);</li>
<li>
</ul>
<p>+/* Let <code>exp</code> be such that <code>number</code> is written as: "0.#{digits}e#{exp}",</p>
<ul>
<li>i.e. such that 10 ** (exp - 1) <= |number| < 10 ** exp</li>
<li>Recall that up to 17 digits can be needed to represent a double,</li>
<li>so if ndigits + exp >= 17, the intermediate value (number * 10 ** ndigits)</li>
<li>will be an integer and thus the result is the original number.</li>
<li>If ndigits + exp <= 0, the result is 0 or "1e#{exp}", so</li>
<li>if ndigits + exp < 0, the result is 0.</li>
<li>We have:</li>
<li>
<pre><code> 2 ** (binexp-1) <= |number| < 2 ** binexp
</code></pre>
</li>
<li>
<pre><code> 10 ** ((binexp-1)/log_2(10)) <= |number| < 10 ** (binexp/log_2(10))
</code></pre>
</li>
<li>
<pre><code> If binexp >= 0, and since log_2(10) = 3.322259:
</code></pre>
</li>
<li>
<pre><code> 10 ** (binexp/4 - 1) < |number| < 10 ** (binexp/3)
</code></pre>
</li>
<li>
<pre><code> binexp/4 <= exp <= binexp/3
</code></pre>
</li>
<li>
<pre><code> If binexp <= 0, swap the /4 and the /3
</code></pre>
</li>
<li>
<pre><code> So if ndigits + binexp/(3 or 4) >= 17, the result is number
</code></pre>
</li>
<li>
<pre><code> If ndigits + binexp/(4 or 3) < 0 the result is 0
</code></pre>
</li>
</ul>
<p>+*/</p>
<ul>
<li>if ((long)ndigits * (4 - (binexp < 0)) + binexp < 0) {</li>
<li>
<pre><code> number = 0;
</code></pre>
</li>
<li>}</li>
<li>else if ((long)(ndigits - 17) * (3 + (binexp < 0)) + binexp < 0) {</li>
<li>
<pre><code> f = pow(10, abs(ndigits));
if (ndigits < 0) {
double absnum = fabs(number);
if (absnum < f) return INT2FIX(0);
</code></pre>
</li>
</ul> Ruby master - Bug #5179 (Closed): Complex#rationalize and to_r with approximate zeroshttps://bugs.ruby-lang.org/issues/51792011-08-10T10:41:15Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Currently, Complex#rationalize and Complex#to_r raise a RangeError if the imaginary part is nonzero <em>or is a Float</em>. Note that a BigDecimal(0) is accepted, though:</p>
<pre><code>Complex(1, 0).to_r # => Rational(1,1)
Complex(1, BigDecimal("0.0")).to_r # => Rational(1,1)
Complex(1, 0.0).to_r # => RangeError
</code></pre>
<p>This is inconsistent. I recommend not raising an error for 0.0 (Float or BigDecimal). Any objection?</p> Ruby master - Bug #5178 (Closed): Complex#rationalize should rationalizehttps://bugs.ruby-lang.org/issues/51782011-08-10T10:39:36Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Complex#rationalize currently calls <code>to_r</code> on the real part instead of <code>rationalize</code>:</p>
<p>f = 1/3.0<br>
c = Complex(f)<br>
c.to_r == f.to_r # => true<br>
c.rationalize == f.rationalize # => false</p>
<p>Should I not commit this to 1.9.3 too?</p>
<p>diff --git a/complex.c b/complex.c<br>
index 78f0902..1b76074 100644<br>
--- a/complex.c<br>
+++ b/complex.c<br>
@@ -1335,7 +1335,8 @@ nucomp_to_f(VALUE self)</p>
<ul>
<li>call-seq:</li>
<li>cmp.to_r -> rational</li>
<li>
</ul>
<ul>
<li>
<ul>
<li>Returns the value as a rational if possible.</li>
</ul>
</li>
</ul>
<ul>
<li>
<ul>
<li>If the imaginary part is exactly 0, returns the real part as a Rational,</li>
</ul>
</li>
<li>
<ul>
<li>otherwise a RangeError is raised.<br>
*/<br>
static VALUE<br>
nucomp_to_r(VALUE self)<br>
@@ -1354,14 +1355,22 @@ nucomp_to_r(VALUE self)</li>
<li>call-seq:</li>
<li>cmp.rationalize([eps]) -> rational</li>
<li>
</ul>
</li>
</ul>
<ul>
<li>
<ul>
<li>Returns the value as a rational if possible. An optional argument</li>
</ul>
</li>
<li>
<ul>
<li>eps is always ignored.</li>
</ul>
</li>
</ul>
<ul>
<li>
<ul>
<li>If the imaginary part is exactly 0, returns the real part as a Rational,</li>
</ul>
</li>
<li>
<ul>
<li>otherwise a RangeError is raised.<br>
*/<br>
static VALUE<br>
nucomp_rationalize(int argc, VALUE *argv, VALUE self)<br>
{</li>
</ul>
</li>
<li>get_dat1(self);</li>
<li>rb_scan_args(argc, argv, "01", NULL);</li>
</ul>
<ul>
<li>return nucomp_to_r(self);</li>
</ul>
<ul>
<li>
<li>if (k_inexact_p(dat->imag) || f_nonzero_p(dat->imag)) {</li>
<li>
<pre><code> VALUE s = f_to_s(self);
</code></pre>
</li>
<li>
<pre><code> rb_raise(rb_eRangeError, "can't convert %s into Rational",
</code></pre>
</li>
<li>
<pre><code> StringValuePtr(s));
</code></pre>
</li>
<li>}</li>
<li>return rb_funcall(dat->real, rb_intern("rationalize"), argc, argv);<br>
}</li>
</ul> Ruby master - Bug #5070 (Closed): CSV.generate should not modify the given option hashhttps://bugs.ruby-lang.org/issues/50702011-07-22T04:23:02Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Currently:</p>
<pre><code>CSV.generate( {}.freeze ) # => RuntimeError: can't modify frozen Hash
</code></pre>
<p>I'm not sure where these tests would ideally go; In the attached patch, I've put them at the end of csv/test_interface</p>
<p>If you can, please make the modifications you see fit, or else I'll commit this in a of week or two.</p>
<p>(From <a href="http://stackoverflow.com/questions/6759487/ruby-hash-object-changed-by-csv-library" class="external">http://stackoverflow.com/questions/6759487/ruby-hash-object-changed-by-csv-library</a> )</p> Ruby master - Feature #4938 (Closed): Add Random.bytes [patch]https://bugs.ruby-lang.org/issues/49382011-06-28T00:58:10Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>It could be useful to add a <code>Random.bytes</code> method (equivalent to <code>Random::DEFAULT.bytes</code>), as per the simple patch attached.</p> Ruby master - Feature #3715 (Rejected): Enumerator#size and #size=https://bugs.ruby-lang.org/issues/37152010-08-19T05:02:27Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
It would be useful to be able to ask an Enumerator for the number of times it will yield, without having to actually iterate it.</p>
<p>For example:</p>
<p>(1..1000).to_a.permutation(4).size # => 994010994000 (instantly)</p>
<p>It would allow nice features like:</p>
<p>class Enumerator<br>
def with_progress<br>
return to_enum :with_progress unless block_given?<br>
out_of = size || "..."<br>
each_with_index do |obj, i|<br>
puts "Progress: #{i} / #{out_of}"<br>
yield obj<br>
end<br>
puts "Done"<br>
end<br>
end</p>
<a name="To-display-the-progress-of-any-iterator-one-can-daisy-chain-with_progress"></a>
<h1 >To display the progress of any iterator, one can daisy-chain with_progress:<a href="#To-display-the-progress-of-any-iterator-one-can-daisy-chain-with_progress" class="wiki-anchor">¶</a></h1>
<p>20.times.with_progress.map do<br>
# do stuff here...<br>
end</p>
<p>This would print out "Progress: 1 / 20", etc..., while doing the stuff.</p>
<p>*** Proposed changes ***</p>
<ul>
<li>Enumerator#size *</li>
</ul>
<p>call-seq:<br>
e.size -> int, Float::INFINITY or nil<br>
e.size {block} -> int</p>
<p>Returns the size of the enumerator.<br>
The form with no block given will do a lazy evaluation of the size without going through the enumeration. If the size can not be determined then +nil+ is returned.<br>
The form with a block will always iterate through the enumerator and return the number of times it yielded.</p>
<p>(1..100).to_a.permutation(4).size # => 94109400<br>
loop.size # => Float::INFINITY</p>
<p>a = [1, 2, 3]<br>
a.keep_if.size # => 3<br>
a # => [1, 2, 3]<br>
a.keep_if.size{false} # => 3<br>
a # => []</p>
<p>[1, 2, 3].drop_while.size # => nil<br>
[1, 2, 3].drop_while.size{|i| i < 3} # => 2</p>
<ul>
<li>Enumerator#size= *</li>
</ul>
<p>call-seq:<br>
e.size = sz</p>
<p>Sets the size of the enumerator. If +sz+ is a Proc or a Method, it will be called each time +size+ is requested, otherwise +sz+ is returned.</p>
<p>first = [1, 2, 3]<br>
second = [4, 5]<br>
enum = Enumerator.new do |y|<br>
first.each{|o| y << o}<br>
second.each{|o| y << o}<br>
end<br>
enum.size # => nil<br>
enum.size = ->(e){first.size + second.size}<br>
enum.size # => 5<br>
first << 42<br>
enum.size # => 6</p>
<ul>
<li>Kerne#to_enum / enum_for *</li>
</ul>
<p>The only other API change is for #to_enum/#enum_for, which can accept a block for size calculation:</p>
<p>class Date<br>
def step(limit, step=1)<br>
unless block_given?<br>
return to_enum(:step, limit, step){|date| (limit - date).div(step) + 1}<br>
end<br>
# ...<br>
end<br>
end</p>
<p>*** Implementation ***</p>
<p>I implemented the support for #size for most builtin enumerator producing methods (63 in all).</p>
<p>It is broken down in about 20 commits: <a href="http://github.com/marcandre/ruby/commits/enum_size" class="external">http://github.com/marcandre/ruby/commits/enum_size</a></p>
<p>It begins with the implementation of Enumerator#size{=}: <a href="http://github.com/marcandre/ruby/commit/a92feb0" class="external">http://github.com/marcandre/ruby/commit/a92feb0</a></p>
<p>A combined patch is available here: <a href="http://gist.github.com/535974" class="external">http://gist.github.com/535974</a></p>
<p>Still missing are Dir#each, Dir.foreach, ObjectSpace.each_object, Range#step, Range#each, String#upto, String#gsub, String#each_line.</p>
<p>The enumerators whose #size returns +nil+ are:<br>
Array#{r}index, {take|drop}_while<br>
Enumerable#find{_index}, {take|drop}_while<br>
IO: all methods</p>
<p>*** Notes ***</p>
<ul>
<li>Returning +nil+ *</li>
</ul>
<p>I feel it is best if IO.each_line.size and similar return +nil+ to avoid side effects.</p>
<p>We could have Array#find_index.size return the size of the array with the understanding that this is the maximum number of times the enumerator will yield. Since a block can always contain a break statement, size could be understood as a maximum anyways, so it can definitely be argued that the definition should be the maximum number of times.</p>
<ul>
<li>Arguments to size proc/lambda *</li>
</ul>
<p>My implementation currently passes the object that the enumerator will call followed with any arguments given when building the enumerator.</p>
<p>If Enumerator had getters (say Enumerator#base, Enumerator#call, Enumerator#args, see feature request <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Add getters for Enumerator (Closed)" href="https://bugs.ruby-lang.org/issues/3714">#3714</a>), passing the enumerator itself might be a better idea.</p>
<ul>
<li>Does not dispatch through name *</li>
</ul>
<p>It might be worth noting that the size dispatch is decided when creating the enumerator, not afterwards in function of the class & method name:</p>
<p>[1,2,3].permutation(2).size # => 6<br>
[1,2,3].to_enum(:permutation, 2).size # => nil</p>
<ul>
<li>Size setter *</li>
</ul>
<p>Although I personally like the idea that #size= can accept a Proc/Lambda for later call, this has the downside that there is no getter, i.e. no way to get the Proc/Lambda back. I feel this is not an issue, but an alternative would be to have a #size_proc and #size_proc= setters too (like Hash).</p>
<p>I believe this addresses feature request <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: the length for an enumerator generated by Array#permutation and Array#combination (Closed)" href="https://bugs.ruby-lang.org/issues/2673">#2673</a>, although maybe in a different fashion. <a href="http://redmine.ruby-lang.org/issues/show/2673" class="external">http://redmine.ruby-lang.org/issues/show/2673</a><br>
=end</p> Ruby master - Feature #3714 (Closed): Add getters for Enumeratorhttps://bugs.ruby-lang.org/issues/37142010-08-19T04:51:48Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Given an enumerator, there is no way to know what receiver, method and arguments it is based upon (although one could use Enumerator#inspect and parse it to get the method).</p>
<p>For sake of completeness and introspection, it could be useful to have access to them.</p>
<p>This patch adds Enumerator#receiver, #method and #arguments: <a href="http://github.com/marcandre/ruby/commit/fd4c17f7fd" class="external">http://github.com/marcandre/ruby/commit/fd4c17f7fd</a></p>
<p>Note that for Enumerator created with a block like Enumerator.new{|y| y << 1 << 2}, then receiver is a Enumerator::Generator, method is :each and arguments is []. This is consistent with inspect.</p>
<p>Thanks.<br>
=end</p> Backport191 - Backport #3506 (Closed): Kernel::URI with optional parserhttps://bugs.ruby-lang.org/issues/35062010-06-30T05:43:40Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Kernel::URI could accept an optional parameter to specify a parser.</p>
<p>It could then be used in a couple of places in the library itself.</p>
<p>Patch follows:</p>
<p>diff --git a/lib/uri/common.rb b/lib/uri/common.rb<br>
index bda6718..f9f0a6a 100644<br>
--- a/lib/uri/common.rb<br>
+++ b/lib/uri/common.rb<br>
@@ -185,14 +185,7 @@ module URI<br>
end</p>
<pre><code> def join(*uris)
</code></pre>
<ul>
<li>
<pre><code> case uris[0]
</code></pre>
</li>
<li>
<pre><code> when Generic
</code></pre>
</li>
<li>
<pre><code> when String
</code></pre>
</li>
<li>
<pre><code> uris[0] = self.parse(uris[0])
</code></pre>
</li>
<li>
<pre><code> else
</code></pre>
</li>
<li>
<pre><code> raise ArgumentError,
</code></pre>
</li>
<li>
<pre><code> "bad argument(expected URI object or URI string)"
</code></pre>
</li>
<li>
<pre><code> end
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> uris[0] = URI(uris[0], self)
uris.inject :merge
</code></pre>
end</li>
</ul>
<p>@@ -845,12 +838,12 @@ module Kernel<br>
#<br>
# Returns +uri+ converted to a URI object.<br>
#</p>
<ul>
<li>def URI(uri)</li>
</ul>
<ul>
<li>def URI(uri, parser = URI::DEFAULT_PARSER)<br>
case uri<br>
when URI::Generic<br>
uri<br>
when String</li>
</ul>
<ul>
<li>
<pre><code> URI.parse(uri)
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> parser.parse(uri)
</code></pre>
else<br>
raise ArgumentError,<br>
"bad argument (expected URI object or URI string)"<br>
diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb<br>
index 4fdfd14..4084b56 100644<br>
--- a/lib/uri/generic.rb<br>
+++ b/lib/uri/generic.rb<br>
@@ -783,14 +783,7 @@ module URI
<a name="return-base-and-rel"></a>
<h1 >return base and rel.<a href="#return-base-and-rel" class="wiki-anchor">¶</a></h1>
<a name="you-can-modify-base-but-can-not-rel"></a>
<h1 >you can modify <code>base', but can not </code>rel'.<a href="#you-can-modify-base-but-can-not-rel" class="wiki-anchor">¶</a></h1>
def merge0(oth)</li>
</ul>
<ul>
<li>
<pre><code> case oth
</code></pre>
</li>
<li>
<pre><code> when Generic
</code></pre>
</li>
<li>
<pre><code> when String
</code></pre>
</li>
<li>
<pre><code> oth = parser.parse(oth)
</code></pre>
</li>
<li>
<pre><code> else
</code></pre>
</li>
<li>
<pre><code> raise ArgumentError,
</code></pre>
</li>
<li>
<pre><code> "bad argument(expected URI object or URI string)"
</code></pre>
</li>
<li>
<pre><code> end
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> oth = URI(oth, parser)
if self.relative? && oth.relative?
raise BadURIError,
</code></pre>
</li>
</ul>
<p>@@ -854,15 +847,7 @@ module URI<br>
private :route_from_path</p>
<pre><code> def route_from0(oth)
</code></pre>
<ul>
<li>
<pre><code> case oth
</code></pre>
</li>
<li>
<pre><code> when Generic
</code></pre>
</li>
<li>
<pre><code> when String
</code></pre>
</li>
<li>
<pre><code> oth = parser.parse(oth)
</code></pre>
</li>
<li>
<pre><code> else
</code></pre>
</li>
<li>
<pre><code> raise ArgumentError,
</code></pre>
</li>
<li>
<pre><code> "bad argument(expected URI object or URI string)"
</code></pre>
</li>
<li>
<pre><code> end
</code></pre>
</li>
<li>
</ul>
<ul>
<li>
<pre><code> oth = URI(oth, parser)
if self.relative?
raise BadURIError,
"relative URI: #{self}"
</code></pre>
</li>
</ul>
<p>@@ -966,16 +951,7 @@ module URI<br>
# #=> #<URI::Generic:0x2020c2f6 URL:/main.rbx?page=1><br>
#<br>
def route_to(oth)</p>
<ul>
<li>
<pre><code> case oth
</code></pre>
</li>
<li>
<pre><code> when Generic
</code></pre>
</li>
<li>
<pre><code> when String
</code></pre>
</li>
<li>
<pre><code> oth = parser.parse(oth)
</code></pre>
</li>
<li>
<pre><code> else
</code></pre>
</li>
<li>
<pre><code> raise ArgumentError,
</code></pre>
</li>
<li>
<pre><code> "bad argument(expected URI object or URI string)"
</code></pre>
</li>
<li>
<pre><code> end
</code></pre>
</li>
<li>
<li>
<pre><code> oth.route_from(self)
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> URI(oth, parser).route_from(self)
</code></pre>
<p>end</p>
<h1></h1>
</li>
</ul>
<p>=end</p> Backport191 - Backport #3505 (Closed): URI.join and Kernel::URI should accept URI objectshttps://bugs.ruby-lang.org/issues/35052010-06-30T05:38:02Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
URI.join accepts strings or URI objects, except for the first parameter which must be a string:</p>
<p>rubydev -r uri -e 'p URI.join("<a href="http://ruby-lang.org" class="external">http://ruby-lang.org</a>", URI("/foo"))'<br>
#<URI::HTTP:0x0000010109b418 URL:<a href="http://ruby-lang.org/foo%3E" class="external">http://ruby-lang.org/foo></a></p>
<p>rubydev -r uri -e 'p URI.join(URI("<a href="http://ruby-lang.org" class="external">http://ruby-lang.org</a>"), "/foo")'<br>
/usr/local/rubydev/lib/ruby/1.9.1/uri/common.rb:156:in `split': bad URI(is not URI?): <a href="http://ruby-lang.org" class="external">http://ruby-lang.org</a> (URI::InvalidURIError)</p>
<p>I believe it should accept URI object as first parameter too.</p>
<p>Also, Kernel::URI accept uri strings, but not URI objects:</p>
<p>rubydev -r uri -e 'URI(URI("<a href="http://ruby-lang.org" class="external">http://ruby-lang.org</a>"))'<br>
/usr/local/rubydev/lib/ruby/1.9.1/uri/common.rb:156:in `split': bad URI(is not URI?): <a href="http://ruby-lang.org" class="external">http://ruby-lang.org</a> (URI::InvalidURIError)</p>
<p>This corresponds to the documentation, but it is contrary to Kernel::String, Integer, Float, etc... that all accept their own type. The error message is clearly buggy (an URI object is not an invalid uri!).</p>
<p>I believe that Kernel::URI should accept URI objects (and return them).</p>
<p>The patch below corrects both and has no impact on test-all nor rubyspec.</p>
<p>I plan to commit it unless there is objection.</p>
<p>Yugui: should I commit it in the 1.9.2 branch too?</p>
<p>Thanks</p>
<p>diff --git a/lib/uri/common.rb b/lib/uri/common.rb<br>
index 58fd422..bda6718 100644<br>
--- a/lib/uri/common.rb<br>
+++ b/lib/uri/common.rb<br>
@@ -184,12 +184,16 @@ module URI<br>
end<br>
end</p>
<ul>
<li>def join(*str)</li>
<li>
<pre><code> u = self.parse(str[0])
</code></pre>
</li>
<li>
<pre><code> str[1 .. -1].each do |x|
</code></pre>
</li>
<li>
<pre><code> u = u.merge(x)
</code></pre>
</li>
</ul>
<ul>
<li>def join(*uris)</li>
<li>
<pre><code> case uris[0]
</code></pre>
</li>
<li>
<pre><code> when Generic
</code></pre>
</li>
<li>
<pre><code> when String
</code></pre>
</li>
<li>
<pre><code> uris[0] = self.parse(uris[0])
</code></pre>
</li>
<li>
<pre><code> else
</code></pre>
</li>
<li>
<pre><code> raise ArgumentError,
</code></pre>
</li>
<li>
<pre><code> "bad argument (expected URI object or URI string)"
end
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> u
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> uris.inject :merge
</code></pre>
<p>end</p>
<p>def extract(str, schemes = nil, &block)<br>
@@ -837,11 +841,20 @@ module URI<br>
end</p>
</li>
</ul>
<p>module Kernel</p>
<ul>
<li>
<a name="alias-for-URIparse"></a>
<h1 >alias for URI.parse.<a href="#alias-for-URIparse" class="wiki-anchor">¶</a></h1>
</li>
</ul>
<ul>
<li>
<h1></h1>
</li>
</ul>
<ul>
<li>
<a name="This-method-is-introduced-at-182"></a>
<h1 >This method is introduced at 1.8.2.<a href="#This-method-is-introduced-at-182" class="wiki-anchor">¶</a></h1>
</li>
<li>def URI(uri_str) # :doc:</li>
<li>URI.parse(uri_str)</li>
</ul>
<ul>
<li>
<a name="Returns-uri-converted-to-a-URI-object"></a>
<h1 >Returns +uri+ converted to a URI object.<a href="#Returns-uri-converted-to-a-URI-object" class="wiki-anchor">¶</a></h1>
</li>
<li>
<h1></h1>
</li>
<li>def URI(uri)</li>
<li>case uri</li>
<li>when URI::Generic</li>
<li>
<pre><code> uri
</code></pre>
</li>
<li>when String</li>
<li>
<pre><code> URI.parse(uri)
</code></pre>
</li>
<li>else</li>
<li>
<pre><code> raise ArgumentError,
</code></pre>
</li>
<li>
<pre><code> "bad argument (expected URI object or URI string)"
</code></pre>
</li>
<li>end<br>
end<br>
module_function :URI<br>
end<br>
=end</li>
</ul> Ruby master - Bug #3448 (Rejected): broken iconv libraryhttps://bugs.ruby-lang.org/issues/34482010-06-17T13:08:27Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Texts longer than ~8160 characters can create problems with iconv on some distributions:</p>
<p>require 'iconv'<br>
Iconv.conv("iso-8859-1//ignore", "utf-8", "\305\253" + "a"*8159).size #=> 8159<br>
Iconv.conv("iso-8859-1//ignore", "utf-8", "\305\253" + "a"*8160).size # => Iconv::IllegalSequence: "a"</p>
<p>The code above is from Debian 4 and 5 (on Heroku...), but it works as expected on OS X. As such, it affects Ruby 1.8 and 1.9</p>
<p>A google search reassured me I was not crazy, e.g. my_iconv_open in:<br>
<a href="http://www.opensource.apple.com/source/vim/vim-6/vim/src/mbyte.c" class="external">http://www.opensource.apple.com/source/vim/vim-6/vim/src/mbyte.c</a></p>
<a name="I-realize-this-is-somewhat-a-third-party-issue-but-Im-logging-this-nevertheless-as-a-brave-soul-might-bypass-the-bug-in-the-Ruby-library-andor-report-this-to-the-proper-authorities"></a>
<h2 >I realize this is somewhat a third party issue, but I'm logging this nevertheless, as a brave soul might bypass the bug in the Ruby library and/or report this to the proper authorities.<a href="#I-realize-this-is-somewhat-a-third-party-issue-but-Im-logging-this-nevertheless-as-a-brave-soul-might-bypass-the-bug-in-the-Ruby-library-andor-report-this-to-the-proper-authorities" class="wiki-anchor">¶</a></h2>
<p>Marc-André<br>
=end</p> Ruby master - Bug #3434 (Closed): Specs for coercion?https://bugs.ruby-lang.org/issues/34342010-06-13T15:29:24Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
What are the official specs of coercion for mathematical classes?</p>
<p>I will take Matrix as an example, but my questions are meant to be for the general case.</p>
<p>My understanding is that for a <code>obj.coerce(obj_2)</code> should return <code>[compatible_2, compatible]</code> such that <code>compatible2.send(some_operation, compatible)</code> returns (if possible) a meaningful result.</p>
<p>Can we assume anything more about coercion? I'm asking because I find in test_matrix (@m1 being a Matrix):</p>
<p>def test_scalar_mul<br>
s1 = @m1.coerce(1).first<br>
assert_equal(Matrix[[1]], (s1 * 1) * Matrix[[1]])<br>
assert_equal(Vector[2], s1 * Vector[2])<br>
assert_equal(Matrix[[2]], s1 * Matrix[[2]])<br>
o = Object.new<br>
def o.coerce(x)<br>
[1, 1]<br>
end<br>
assert_equal(1, s1 * o)<br>
end</p>
<ol>
<li>Should the first and last assert work? Are implementers of other mathematical classes mandated/encouraged to provide that level of compatibility? Are users of <code>coerce</code> encouraged (or guaranteed success) when doing any other operation than <code>compatible2 * compatible</code> or similar?</li>
</ol>
<p>My feeling is that the only thing one should do with the results of coerce is to call an operation on the first element and pass the second element. Doing operations using only one of the two returned elements with another new object should yield undetermined results.</p>
<p>If this is the case, I feel the Matrix library would be best to assume that Scalar#* is called with a Matrix or Vector (remember that the Scalar is not meant to be used directly by anybody else than the Matrix lib), and these two assert would <em>not</em> work.</p>
<ol start="2">
<li>
<p>The second assert is clearly implementation dependant. In the current implementation, both Vector and Matrix use Matrix::Scalar as a temporary class, but that could change.</p>
</li>
<li>
<p>I am assuming that compatible doesn't have to be equal?, eql? or == to obj nor of the same class, and the same is true for compatible_2 vs obj_2, right? Thus the third assert isn't a spec guaranteed for all implementations.</p>
</li>
<li>
<p>Finally, a somewhat trivial question: should <code>obj.coerce(obj_2)</code> succeed if <code>obj</code> and <code>obj_2</code> are of the same class (and presumably return <code>[obj_2, obj]</code>)? Clearly this is not very useful, but the specs should be made precise.</p>
</li>
</ol>
<p>This is the case for Numeric and is explicit in the documentation but fails for Matrix:</p>
<pre><code> Matrix.I(2).coerce(Matrix.I(2)) # => TypeError: Matrix can't be coerced into Matrix
</code></pre>
<p>Coercion should always work for the trivial case of two objects of the same class, right?</p>
<a name="Thanks"></a>
<h2 >Thanks.<a href="#Thanks" class="wiki-anchor">¶</a></h2>
<p>Marc-André<br>
=end</p> Ruby master - Bug #3352 (Rejected): Delegates: protected methodshttps://bugs.ruby-lang.org/issues/33522010-05-27T15:55:26Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
require 'delegate'</p>
<pre><code> class X
protected
def pro
:foo
end
end
obj = X.new
obj.pro #=> NoMethodError: protected method `pro' called for #<X:0x000001008a2a68>
SimpleDelegator.new(obj).pro #=> :foo
</code></pre>
<p>I feel it would be more sensible to raise a NoMethodError.</p>
<p>No test seem to be testing for protected access, nor does RubySpec.</p>
<p>Unless there is objection, I'll commit the following:</p>
<p>diff --git a/lib/delegate.rb b/lib/delegate.rb<br>
index f366091..93fbc37 100644<br>
--- a/lib/delegate.rb<br>
+++ b/lib/delegate.rb<br>
@@ -141,7 +141,7 @@ class Delegator < BasicObject<br>
def method_missing(m, *args, &block)<br>
target = self.<strong>getobj</strong><br>
begin</p>
<ul>
<li>
<pre><code> target.respond_to?(m) ? target.__send__(m, *args, &block) : super(m, *args, &block)
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> target.respond_to?(m) ? target.public_send(m, *args, &block) : super
</code></pre>
ensure<br>
$@.delete_if {|t| %r"\A#{Regexp.quote(<strong>FILE</strong>)}:#{<strong>LINE</strong>-2}:"o =~ t} if $@<br>
end<br>
=end</li>
</ul> Ruby master - Bug #3350 (Closed): Protected methods & documentationhttps://bugs.ruby-lang.org/issues/33502010-05-27T15:28:46Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The official doc currently states that Object#methods "returns a list of the names of methods publicly accessible".</p>
<p>Similarly, Module#instance_methods states that it returns "the public methods" of the Module. Note that the doc was modified in r19900, but I feel the wording "instance method that is callable from outside" still implies public only.</p>
<p>The current behavior doesn't fit the doc, since protected methods are also matched:</p>
<pre><code> class X
def protected_method; end
protected :protected_method
end
X.new.methods.include?(:protected_method) #=> true
X.instance_methods.include?(:protected_method) #=> true
</code></pre>
<p>The documentation for Module#method_defined? on the other states it matches public and protected methods.</p>
<p>Should I change the doc to reflect the current behavior, as per the patch below?</p>
<p>I'm asking in part because I lack experience with protected methods and I am surprised by the fact that protected methods are matched by these "default" methods.</p>
<p>The fact that Object#respond_to? also matches protected is even less practical since there is no "public-only" equivalent. I might be mistaken, but I believe that the only way of knowing if obj responds publicly to :foo is to do something like</p>
<pre><code> publicly_responds = obj.public_method(:foo) rescue false
</code></pre>
<p>I dislike the fact that obj.respond_to?(:foo) && obj.foo might raise a NoMethodError.</p>
<p>It looks like this was discussed a in [ruby_dev:40461], but I don't know the outcome.</p>
<p>I'm curious: what examples exist where one would want to match public and protected methods but not private ones?</p>
<p>Matz, is there any chance the handling of #respond_to?, #methods, etc..., with regards to protected methods will change (in 1.9.2 or later)?</p>
<p>--<br>
Marc-André</p>
<p>diff --git a/class.c b/class.c<br>
index c586f7a..683fa7b 100644<br>
--- a/class.c<br>
+++ b/class.c<br>
@@ -865,8 +865,8 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, lo</p>
<ul>
<li>call-seq:</li>
<li>
<pre><code>mod.instance_methods(include_super=true) -> array
</code></pre>
</li>
<li>
</ul>
<ul>
<li>
<ul>
<li>Returns an array containing the names of instance methods that is callable</li>
</ul>
</li>
<li>
<ul>
<li>from outside in the receiver. For a module, these are the public methods;</li>
</ul>
</li>
</ul>
<ul>
<li>
<ul>
<li>Returns an array containing the names of the public and protected instance</li>
</ul>
</li>
<li>
<ul>
<li>methods in the receiver. For a module, these are the public and protected methods;</li>
<li>for a class, they are the instance (not singleton) methods. With no</li>
<li>argument, or with an argument that is <code>false</code>, the</li>
<li>instance methods in <i>mod</i> are returned, otherwise the methods<br>
@@ -954,6 +954,7 @@ rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)</li>
<li>Returns an array of the names of singleton methods for <i>obj</i>.</li>
<li>If the optional <i>all</i> parameter is true, the list will include</li>
<li>methods in modules included in <i>obj</i>.</li>
</ul>
</li>
<li>
<ul>
<li>Only public and protected singleton methods are returned.</li>
<li>
<li>
<pre><code>module Other
</code></pre>
</li>
<li>
<pre><code> def three() end
</code></pre>
</li>
</ul>
</li>
</ul>
<p>diff --git a/object.c b/object.c<br>
index a7f05a1..351d16f 100644<br>
--- a/object.c<br>
+++ b/object.c<br>
@@ -1755,7 +1755,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)</p>
<ul>
<li>call-seq:</li>
<li>
<pre><code>obj.methods -> array
</code></pre>
</li>
<li>
</ul>
<ul>
<li>
<ul>
<li>Returns a list of the names of methods publicly accessible in</li>
</ul>
</li>
</ul>
<ul>
<li>
<ul>
<li>Returns a list of the names of public and protected methods of</li>
<li>
<i>obj</i>. This will include all the methods accessible in</li>
<li>
<i>obj</i>'s ancestors.</li>
<li>
</ul>
</li>
</ul>
<p>=end</p> Ruby 1.8 - Backport #3273 (Closed): Float string conversionhttps://bugs.ruby-lang.org/issues/32732010-05-11T14:12:19Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
For any float f, the two following conditions should hold:<br>
(1) f.to_s.to_f == f (round trips)<br>
(2) f.to_s.chop.to_f != f (minimal)</p>
<p>The second condition is a simplification; if the string representation is in scientific notation, than the character to remove would be the one just before the "e". Also, if the string representation ends with ".0", then it is minimal.</p>
<p>Currently, the first condition fails in Ruby 1.8, and the second fails in Ruby 1.9</p>
<p>$ ruby18dev -ve 'f = 0.21611564636388508; puts f.to_s.to_f == f'<br>
ruby 1.8.8dev (2010-05-11) [i386-darwin10.3.0]<br>
false</p>
<p>$ rubydev -ve 'f = 0.56; puts f.to_s.chop.to_f != f'<br>
ruby 1.9.3dev (2010-05-11 trunk 27730) [x86_64-darwin10.3.0]<br>
false</p>
<p>Note that this implies that Ruby 1.8 and 1.9 do not output the same string representation for either of these two floats.</p>
<p>The conversion algorithm currently checks two precisions. In Ruby 1.9, it tries 16 digits and if that's not enough it then uses 17. In 1.8, it's the same but with 15 and 16.</p>
<p>The fact is that 17 can be necessary (e.g. 0.21611564636388508 is not equal to either 0.2161156463638851 or 0.2161156463638850) and 16 can be too much (e.g. 0.5600000000000001 == 0.56), so three precisions must be checked.</p>
<p>The following patch fixes this issue for trunk (although it can probably be made nicer and/or faster).</p>
<p>Let me know if there are any objections to fixing both the 1.9 and 1.8 lines.</p>
<p>diff --git a/numeric.c b/numeric.c<br>
index f2c8c13..442b069 100644<br>
--- a/numeric.c<br>
+++ b/numeric.c<br>
@@ -569,7 +569,8 @@ flo_to_s(VALUE flt)<br>
else if (isnan(value))<br>
return rb_usascii_str_new2("NaN");</p>
<p>-# define FLOFMT(buf, size, fmt, prec, val) snprintf(buf, size, fmt, prec, val), <br>
+# define FLOFMT(buf, size, fmt, prec, val) snprintf(buf, size, fmt, prec-1, val), \</p>
<ul>
<li>
<p>(void)((atof(buf) == val) || snprintf(buf, size, fmt, (prec), val)), <br>
(void)((atof(buf) == val) || snprintf(buf, size, fmt, (prec)+1, val))</p>
<p>FLOFMT(buf, sizeof(buf), "%#.<em>g", float_dig, value); /</em> ensure to print decimal point */<br>
=end</p>
</li>
</ul> Ruby master - Bug #3225 (Closed): lib/uri/mailto.rb slightly wrong regexphttps://bugs.ruby-lang.org/issues/32252010-04-30T13:24:56Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Looking for example of the 3rd parameter of value 'N' for Regexp.new, I noticed in lib/uri/mailto.rb</p>
<p>HEADER_REGEXP = Regexp.new(HEADER_PATTERN, 'N').freeze</p>
<p>Unless I'm mistaken, the 'N' in second position is simply a flag for case insensitivity, but HEADER_PATTERN already is, so it should either be</p>
<p>HEADER_REGEXP = Regexp.new(HEADER_PATTERN).freeze</p>
<p>or</p>
<p>HEADER_REGEXP = Regexp.new(HEADER_PATTERN, nil, 'N').freeze</p>
<p>but I don't know which one...<br>
=end</p> Ruby master - Bug #3224 (Closed): Regexp.new("...", nil, "n") is not documentedhttps://bugs.ruby-lang.org/issues/32242010-04-30T13:15:06Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
While fixing the error messages for the number of parameters ( r27558 ), I noticed that Regexp.new accepts a third undocumented parameter.</p>
<p>Is it supported? If so it should be documented.</p>
<p>I also note that test_regexp.rb tests for the third parameter being "u", even though this has no effect. Maybe these tests should be removed?<br>
=end</p> Ruby master - Feature #3222 (Closed): Can bignums have singleton class & methods?https://bugs.ruby-lang.org/issues/32222010-04-30T07:07:08Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Fixing up the rubyspecs led me to the following:</p>
<p>bn = 1 << 100<br>
class << bn<br>
def foo<br>
42<br>
end<br>
end</p>
<a name="gt-TypeError-cant-define-singleton-method-foo-for-Bignum"></a>
<h1 >=> TypeError: can't define singleton method "foo" for Bignum<a href="#gt-TypeError-cant-define-singleton-method-foo-for-Bignum" class="wiki-anchor">¶</a></h1>
<p>bn.define_singleton_method(:foo){42}</p>
<a name="gt-TypeError-cant-define-singleton-method-foo-for-Bignum-2"></a>
<h1 >=> TypeError: can't define singleton method "foo" for Bignum<a href="#gt-TypeError-cant-define-singleton-method-foo-for-Bignum-2" class="wiki-anchor">¶</a></h1>
<p>On the other hand...</p>
<p>module Bar<br>
def foo<br>
42<br>
end<br>
end<br>
class << bn<br>
include Bar<br>
end<br>
bn.foo # => 42</p>
<p>If Ruby won't allow singleton methods for Bignum, then shouldn't it disallow access to the singleton class completely?</p>
<p>See also issue <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: an instance of Bignum can have singleton methods (Closed)" href="https://bugs.ruby-lang.org/issues/601">#601</a><br>
=end</p> Ruby master - Bug #3192 (Closed): Missing Set#keep_if, select! [patch]https://bugs.ruby-lang.org/issues/31922010-04-23T14:40:16Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Set (& SortedSet) were forgotten when adding keep_if and select!</p>
<p>Unless there is objection, I'll commit the attached patch (and add tests to RubySpec).<br>
=end</p> Ruby master - Bug #3169 (Closed): RDoc crossref confused by instance and class methods having sam...https://bugs.ruby-lang.org/issues/31692010-04-19T09:39:40Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The documentation for the two methods below will both have a reference to X.foo (which appeared first). The "See X#foo" should reference to the instance method instead.</p>
<p>class X<br>
# The class method. See X#foo<br>
def self.foo<br>
end</p>
<pre><code> # The instance method. See X.foo
def foo
end
</code></pre>
<p>end<br>
=end</p> Ruby master - Bug #3128 (Closed): Randomness specshttps://bugs.ruby-lang.org/issues/31282010-04-11T15:34:01Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
What should be the Ruby specs for the new Random class (and existing Kernel.{s}rand)?</p>
<p>More precisely: what should one expect of any Ruby implementation?</p>
<p>Several degrees of similarity with MRI are possible:</p>
<p>Say r = Random.new(42) and N is an Integer</p>
<ol start="0">
<li>r.rand(N) is included in 0...N</li>
<li>r.rand(N) will eventually return all values in 0...N</li>
<li>r.rand(N) will return any particular value in 0...N with a probability of around 1/N<br>
<insert any any of the known random tests and/or a minimal period></li>
<li>r is a Mersenne Twister</li>
<li>r is MT19937</li>
<li>r.rand(N) generates the same particular string on all platforms</li>
</ol>
<p>Implementers are ultimately free to choose whichever implementation they prefer, of course.</p>
<p>Still, it would be preferable to state what is the expect behavior for the Ruby language, not just for MRI. If MRI's guarantees are stronger, these should be stated as such.</p>
<p>Current state of affairs:</p>
<p>The documentation for Random class states that it is a Mersenne Twister pseudo number generator (but doesn't state which), so this corresponds to level (3) above.</p>
<p>Kernel.rand states that <em>currently</em>, r is a modified MT19937.</p>
<p>The Ruby Standardization WG Draft doesn't document Kernel.rand yet (nor Random, of course).</p>
<p>Rubinius' implementation currently guarantees level 0 (and also level 1 if N is not too big)</p>
<p>JRuby's implementation guarantees level 1 (and also level 2 if N is not too big)</p>
<p>Python and Java both guarantee the same particular sequence; other algorithms might be available as subclasses of their Random class.</p>
<hr>
<p>My personal choice would be in line with Java and Python: insure the exact same sequence for the Random class. Implementations are free to provide subclasses of Random for different/better/faster algorithms.</p>
<p>If deemed preferable, Kernel.rand could have much lower required standards to allow for better speed, in which case level (2) above seems like the strict minimum.<br>
=end</p> Ruby master - Bug #3104 (Closed): Random: seeding issueshttps://bugs.ruby-lang.org/issues/31042010-04-07T15:08:35Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
I think there are a couple of very small errors with the seeding of the Random class.</p>
<ol>
<li>
<p>Seeding sometimes ignores the high bit of seed data.</p>
<p>Random.new((1<<64)-1).rand == Random.new((1 << 65) -1).rand</p>
<a name="gt-true-should-be-false"></a>
<h1 >=> true, should be false<a href="#gt-true-should-be-false" class="wiki-anchor">¶</a></h1>
</li>
</ol>
<p>Probably some leftover code?</p>
<p>diff --git a/random.c b/random.c<br>
index 02d081c..447e59f 100644<br>
--- a/random.c<br>
+++ b/random.c<br>
@@ -411,8 +411,6 @@ rand_init(struct MT *mt, VALUE vseed)<br>
init_genrand(mt, buf[0]);<br>
}<br>
else {</p>
<ul>
<li>
<pre><code> if (buf[len-1] == 1) /* remove leading-zero-guard */
</code></pre>
</li>
<li>
<pre><code> len--;
init_by_array(mt, buf, len);
</code></pre>
}<br>
if (buf != buf0) xfree(buf);</li>
</ul>
<ol start="2">
<li>
<p>Treatment of negative seed values is currently platform dependent for all negative fixnums. From the same negative seed, the random sequence can be different on 32 bit platforms than on 64 bit ones.</p>
<p>Random.new(-1).rand == Random.new((1<<63) -1).rand</p>
<a name="gt-true-on-64-bit-platform-false-on-32-bit"></a>
<h1 >=> true on 64 bit platform, false on 32 bit<a href="#gt-true-on-64-bit-platform-false-on-32-bit" class="wiki-anchor">¶</a></h1>
<p>Random.new(-1).rand == Random.new((1<<31) -1).rand</p>
<a name="gt-false-on-64-bit-platform-true-on-32-bit"></a>
<h1 >=> false on 64 bit platform, true on 32 bit<a href="#gt-false-on-64-bit-platform-true-on-32-bit" class="wiki-anchor">¶</a></h1>
</li>
</ol>
<p>The simple solution below ignores the sign (which is what's done in case of negative Bignum). This means that the same values will result from seeding with x or -x. Another solution would be to use the lowest bit for the sign (for both fixnums and bignums) so as to avoid this collision, or raise an error in case of negative seeds.</p>
<p>diff --git a/random.c b/random.c<br>
index 02d081c..272f7b5 100644<br>
--- a/random.c<br>
+++ b/random.c<br>
@@ -367,6 +367,7 @@ rand_init(struct MT *mt, VALUE vseed)<br>
{<br>
volatile VALUE seed;<br>
long blen = 0;</p>
<ul>
<li>long fixnum_seed;<br>
int i, j, len;<br>
unsigned int buf0[SIZEOF_LONG / SIZEOF_INT32 * 4], *buf = buf0;</li>
</ul>
<p>@@ -374,9 +375,11 @@ rand_init(struct MT *mt, VALUE vseed)<br>
switch (TYPE(seed)) {<br>
case T_FIXNUM:<br>
len = 1;</p>
<ul>
<li>
<pre><code> buf[0] = (unsigned int)(FIX2ULONG(seed) & 0xffffffff);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> fixnum_seed = FIX2LONG(seed);
</code></pre>
</li>
<li>
<pre><code> if (fixnum_seed < 0) fixnum_seed = -fixnum_seed;
</code></pre>
</li>
<li>
<pre><code> buf[0] = (unsigned int)(fixnum_seed & 0xffffffff);
</code></pre>
</li>
</ul>
<p>#if SIZEOF_LONG > SIZEOF_INT32</p>
<ul>
<li>
<pre><code> if ((buf[1] = (unsigned int)(FIX2ULONG(seed) >> 32)) != 0) ++len;
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> if ((buf[1] = (unsigned int)(fixnum_seed >> 32)) != 0) ++len;
</code></pre>
</li>
</ul>
<p>#endif<br>
break;<br>
case T_BIGNUM:</p>
<ol start="3">
<li>Finally, I was wondering if there wasn't a typo trashing some of the bits in the initial states when seeding with an array:</li>
</ol>
<p>diff --git a/random.c b/random.c<br>
index 02d081c..f3db095 100644<br>
--- a/random.c<br>
+++ b/random.c<br>
@@ -151,7 +151,7 @@ init_by_array(struct MT *mt, unsigned int init_key[], int key_length)<br>
if (i>=N) { mt->state[0] = mt->state[N-1]; i=1; }<br>
}</p>
<ul>
<li>mt->state[0] = 0x80000000U; /* MSB is 1; assuring non-zero initial array */</li>
</ul>
<ul>
<li>mt->state[0] |= 0x80000000U; /* MSB is 1; assuring non-zero initial array */<br>
}</li>
</ul>
<p>static void</p>
<p>These changes will surely create test failures which should be trivial to fix.<br>
=end</p> Ruby master - Bug #3089 (Closed): limited size for Array#combination [patch]https://bugs.ruby-lang.org/issues/30892010-04-04T05:54:56Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
I would expect the following to work, but it raises an error</p>
<p>(0..100).to_a.combination(50).first(42)<br>
# => RangeError: too big for combination</p>
<p>There is a limit of 1 << 31 potential results (or 1 <<63, depending on the platform).</p>
<p>Since there is an explicit test for this, I learned the hard way I better ask if there is a valid reason for this artificial limit for #combination ?</p>
<p>If not, and unless there is objection, I'll commit the attached patch.</p>
<p>Note: I noticed this when implementing the block form of #product where a similar limit exists. Since #product without a block needs to return an array of this size, it is sensible that an error is raised in that case.<br>
When an block is given, though, I didn't see why there should be a limit, so the limitation applies only to the form without a block. This does mean, though, that arr.product(...) might not behave the same as arr.to_enum(:product, ...).to_a, at least until Enumerators have a length method (see issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: the length for an enumerator generated by Array#permutation and Array#combination (Closed)" href="https://bugs.ruby-lang.org/issues/2673">#2673</a>)<br>
=end</p> Ruby master - Bug #3081 (Closed): lib/http wrong behavior for chunked readinghttps://bugs.ruby-lang.org/issues/30812010-04-03T02:25:06Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Take the following code:</p>
<p>require 'net/http'<br>
uri = URI.parse("<a href="http://banners.wunderground.com/banner/krd_condV2/language/www/US/FL/Miami.gif" class="external">http://banners.wunderground.com/banner/krd_condV2/language/www/US/FL/Miami.gif</a>")<br>
http = Net::HTTP.new(uri.host, uri.port)</p>
<p>http.request_get(uri.request_uri) do |res|<br>
res.read_body do |chunk|<br>
puts "read #{chunk.size} bytes"<br>
break<br>
end<br>
puts "Done"<br>
end<br>
puts "Bye"</p>
<p>in Ruby 1.8.7 or in 1.9.2dev, it outputs the following:</p>
<p>read 1024 bytes<br>
Done<br>
/usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:2433:in <code>read_chunked': wrong chunk size line: (Net::HTTPBadResponse) from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:2411:in </code>read_body_0'<br>
from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:2371:in <code>read_body' from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:2396:in </code>body'<br>
from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:2335:in <code>reading_body' from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:1185:in </code>transport_request'<br>
from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:1169:in <code>request' from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:1162:in </code>block in request'<br>
from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:627:in <code>start' from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:1160:in </code>request'<br>
from /usr/local/rubydev/lib/ruby/1.9.1/net/http.rb:1073:in <code>request_get' from b.rb:5:in </code>'</p>
<p>There's apparently nothing wrong with the server; remove the 'break' statement and you get instead:</p>
<p>read 1024 bytes<br>
read 597 bytes<br>
read 2 bytes<br>
Done<br>
Bye<br>
=end</p> Ruby master - Bug #3027 (Closed): Random#rand(nil)https://bugs.ruby-lang.org/issues/30272010-03-28T09:06:42Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Hi Nobu.</p>
<p>Looking at Random#rand, I notice that passing nil has the same result as not passing any argument.</p>
<p>Either it should raise an ArgumentError like the documentation implies, or else the documentation should be modified.</p>
<p>I would argue to raise an error because:</p>
<ul>
<li>it is easy to pass nothing, or pass 1.0 instead, and get the same result if that is what is desired</li>
<li>it could hide an error in the code, where the result is unexpectedly nil but the programmer didn't think about it (like whiny nils in rails)<br>
=end</li>
</ul> Ruby master - Feature #3023 (Closed): RDoc urlshttps://bugs.ruby-lang.org/issues/30232010-03-27T06:08:35Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Currently, rdoc generates url for methods that look like:</p>
<p>.../classes/Enumerable.html#M002713</p>
<p>This has two drawbacks.</p>
<ol>
<li>
<p>This URL is subject to change when methods are added/removed. This makes it impossible to reference the documentation of a method.</p>
</li>
<li>
<p>There is no way to know what method this refers to just by looking at it.</p>
</li>
</ol>
<p>If instead the url looked like:</p>
<p>.../classes/Enumerable.html#map-instance_method</p>
<p>then it would be human readable and RESTful.</p>
<p>The method name simply need to be URI encoded and suffixed with either instance_method, class_method, or -constant.<br>
=end</p> Ruby master - Bug #3022 (Closed): What are $. and ARGF.lineno ?https://bugs.ruby-lang.org/issues/30222010-03-27T04:13:59Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin</p>
<ol>
<li>$. is not officially documented.</li>
</ol>
<p>This makes it difficult to know if it works as expected or not...</p>
<p>The Ruby Prog Language (Flanagan & Matz) states:<br>
"The number of the last line read from the current input file. Equivalent to ARGF.lineno."</p>
<p>This is not true in trunk, as demonstrated by:</p>
<p>$ rubydev -e "<br>
ARGF.gets<br>
File.open('/etc/passwd'){|f| f.gets; f.gets}<br>
p $., ARGF.lineno<br>
" /etc/hosts<br>
2<br>
1</p>
<p>What is the "current input file"? Not clear, but it's not thread local, as shown:</p>
<p>$ rubydev -e "<br>
p $.<br>
Thread.new{File.open('/etc/passwd').gets; p $. }.join;<br>
p $.<br>
"<br>
0<br>
1<br>
1</p>
<ol start="2">
<li>ARGF.lineno does not conform to its doc.</li>
</ol>
<p>The doc states:</p>
<p>Returns the current line number of the current file in ARGF. This value<br>
can be set manually with ARGF.lineno=.</p>
<p>Reading this, I would expect ARGF.lineno to be the same as ARGF.to_io.lineno.</p>
<p>That is not the case:</p>
<p>rubydev -e 'p "#{ARGF.lineno} #{ARGF.to_io.lineno}" while ARGF.gets' /etc/hosts /etc/passwd<br>
"1 1"<br>
"2 2"<br>
...<br>
"25 1"<br>
"26 2"<br>
...</p>
<ol>
<li>
<p>Maybe the best definition would be that $. returns the number of line read operations issued, from the last time an IO was read in the current thread?</p>
</li>
<li>
<p>I suggest the documentation of ARGF.lineno be changed to:</p>
</li>
</ol>
<p>Returns the current line number of ARGF as a whole. This value<br>
can be set manually with ARGF.lineno=.</p>
<p>See also <a href="https://blade.ruby-lang.org/ruby-core/26303">[ruby-core:26303]</a><br>
=end</p> Ruby master - Feature #3021 (Closed): Array#product should accept a block.https://bugs.ruby-lang.org/issues/30212010-03-27T02:59:16Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Array#permutation and #combination will yield to the given block, or else return an enumerator.</p>
<p>I believe Array#product should have been designed the same way.</p>
<p>Returning an enumerator today would break compatibility though.</p>
<p>I suggest that Array#product(&block) yields to the block and returns self. This maintains compatibility while making it possible to produce an enumerable with my_array.to_enum(:product, ...) or to avoid building an intermediate array.</p>
<p>I could implement this feature in time for code freeze.<br>
=end</p> Ruby master - Bug #3016 (Rejected): Enumerable#slice_before and duphttps://bugs.ruby-lang.org/issues/30162010-03-26T14:01:58Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
When writing the specs for slice_before, I was surprised that it doesn't call #dup.</p>
<p>class X<br>
def dup<br>
raise "Hi!"<br>
end<br>
end</p>
<p>[:foo].slice_before(X.new){}.to_a</p>
<a name="gt-foo-I-expected-it-to-raise"></a>
<h1 >==> [[:foo]], I expected it to raise<a href="#gt-foo-I-expected-it-to-raise" class="wiki-anchor">¶</a></h1>
<p>The implementation calls directly rb_obj_dup.</p>
<p>It's a minor issue, but would it not be best to call dup on the argument? Most special needs for #dup can be addressed by initialize_dup, but maybe there are some reasonable cases where some user classes will redefine #dup?</p>
<p>The same question is valid for Enumerable#chunk.</p>
<p>diff --git a/enum.c b/enum.c<br>
index b69d8c9..e6e6adb 100644<br>
--- a/enum.c<br>
+++ b/enum.c<br>
@@ -14,7 +14,7 @@<br>
#include "node.h"</p>
<p>VALUE rb_mEnumerable;<br>
-static ID id_each, id_eqq, id_cmp, id_next, id_size;<br>
+static ID id_each, id_eqq, id_cmp, id_next, id_size, id_dup;</p>
<p>static VALUE<br>
enum_values_pack(int argc, VALUE *argv)<br>
@@ -2189,7 +2189,7 @@ chunk_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)<br>
arg.yielder = yielder;</p>
<pre><code> if (!NIL_P(arg.state))
</code></pre>
<ul>
<li>
<pre><code> arg.state = rb_obj_dup(arg.state);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> arg.state = rb_funcall(arg.state, id_dup, 0, 0);
</code></pre>
<p>rb_block_call(enumerable, id_each, 0, 0, chunk_ii, (VALUE)&arg);<br>
if (!NIL_P(arg.prev_elts))<br>
@@ -2364,7 +2364,7 @@ slicebefore_i(VALUE yielder, VALUE enumerator, int argc, VALUE *argv)<br>
arg.yielder = yielder;</p>
<p>if (!NIL_P(arg.state))</p>
</li>
</ul>
<ul>
<li>
<pre><code> arg.state = rb_obj_dup(arg.state);
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> arg.state = rb_funcall(arg.state, id_dup, 0, 0);
</code></pre>
<p>rb_block_call(enumerable, id_each, 0, 0, slicebefore_ii, (VALUE)&arg);<br>
if (!NIL_P(arg.prev_elts))<br>
@@ -2606,5 +2606,6 @@ Init_Enumerable(void)<br>
id_cmp = rb_intern("<=>");<br>
id_next = rb_intern("next");<br>
id_size = rb_intern("size");</p>
</li>
<li>
<p>id_dup = rb_intern("dup");<br>
}<br>
=end</p>
</li>
</ul> Ruby 1.8 - Bug #3011 (Closed): caller for recursive functionhttps://bugs.ruby-lang.org/issues/30112010-03-25T10:38:53Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
For some reason, Ruby 1.8 will skip multiple copies of the same method. In case of a recursive function call, the behavior is different from Ruby 1.9 and seems wrong.</p>
<p>Here's the rubyspec I just committed:</p>
<pre><code> it "returns one entry per call, even for recursive methods" do
def recurse(n)
return caller if n <= 0
recurse(n-1)
end
(recurse(3).size - recurse(2).size).should == 1
end
</code></pre>
<p>The following patch doesn't seem to yield any new failure with make test, make test-all, nor the caller specs:</p>
<p>diff --git a/eval.c b/eval.c<br>
index 3407548..65fb970 100644<br>
--- a/eval.c<br>
+++ b/eval.c<br>
@@ -6468,9 +6468,6 @@ backtrace(lev)<br>
}<br>
for (; frame && (n = frame->node); frame = frame->prev) {<br>
if (frame->prev && frame->prev->last_func) {</p>
<ul>
<li>
<pre><code> if (frame->prev->node == n) {
</code></pre>
</li>
<li>
<pre><code> if (frame->prev->last_func == frame->last_func) continue;
</code></pre>
</li>
<li>
<pre><code> }
snprintf(buf, BUFSIZ, "%s:%d:in `%s'",
n->nd_file, nd_line(n),
rb_id2name(frame->prev->last_func));
</code></pre>
</li>
</ul>
<p>Nobu, can you recall what was the reason for these lines ( r10593 ) ?<br>
=end</p> Ruby master - Feature #2832 (Closed): Vector#each and Enumerablehttps://bugs.ruby-lang.org/issues/28322010-03-02T18:04:44Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Vector should implement #each and include Enumerable, since it is so Array-like.</p>
<p>Enumerable methods that return an array should probably be specialized to return a Vector (e.g. map, first, ...)</p>
<p>See also <a href="https://blade.ruby-lang.org/ruby-core/28403">[ruby-core:28403]</a>, [redmine:2831]<br>
=end</p> Ruby master - Feature #2831 (Closed): Matrix: each, all?, none?, each_with_index, ....https://bugs.ruby-lang.org/issues/28312010-03-02T17:10:01Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
There is Matrix#collect, but it would be useful to have Matrix#each and include Enumerable.</p>
<p>All methods that return anything else than an array are completely natural: Matrix#all?, Matrix#any?, Matrix#count, Matrix#none?, etc...</p>
<p>Others can be left alone or undefined (#sort, #drop, ...)</p>
<p>Matrix#each_with_index should go over all values, and yield value, row and column</p>
<p>Currently, some basic operations are quite a bit more difficult than they could be. An example: to check if a matrix is composed of Integer:</p>
<a name="Currently-need-to-build-an-intermediate-array"></a>
<h1 >Currently, need to build an intermediate array<a href="#Currently-need-to-build-an-intermediate-array" class="wiki-anchor">¶</a></h1>
<p>m = Matrix[...]<br>
integral = m.row_vectors.all? do |row|<br>
row.all? &:integer?<br>
end</p>
<a name="Could-be"></a>
<h1 >Could be<a href="#Could-be" class="wiki-anchor">¶</a></h1>
<p>integral = m.all? &:integer?</p>
<p>I'll gladly provide precisions on each method and make a patch.<br>
=end</p> Ruby master - Bug #2830 (Closed): Some methods raise ArgumentError instead of TypeErrorhttps://bugs.ruby-lang.org/issues/28302010-03-02T13:45:08Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Some methods of Ruby 1.9 expect integers/reals and call internally nurat_int_value/nurat_int_check. These functions raise an ArgumentError when the argument is not an Integer, instead of a TypeError.</p>
<p>Thus:<br>
42.gcd(:foo) # => ArgumentError, should be TypeError<br>
42.lcm(:foo) # => ditto<br>
42.gcdlcm(:foo) # => ditto<br>
Rational(:foo,1) # => ditto</p>
<p>Note that on the other hand:<br>
Rational(nil, 1) # => TypeError<br>
Rational(:foo) # => TypeError</p>
<p>In a similar fashion:<br>
Complex.rect(nil) # => ArgumentError, should be TypeError<br>
Complex.polar(nil) # => ditto</p>
<p>Unless there is objection, I will commit the following patch (and fix RubySpec):</p>
<p>diff --git a/complex.c b/complex.c<br>
index 214d3a2..6742257 100644<br>
--- a/complex.c<br>
+++ b/complex.c<br>
@@ -377,7 +377,7 @@ nucomp_real_check(VALUE num)<br>
break;<br>
default:<br>
if (!k_numeric_p(num) || !f_real_p(num))</p>
<ul>
<li>
<pre><code> rb_raise(rb_eArgError, "not a real");
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> rb_raise(rb_eTypeError, "not a real");
</code></pre>
}<br>
}</li>
</ul>
<p>diff --git a/rational.c b/rational.c<br>
index 65d3cf4..f5a6d26 100644<br>
--- a/rational.c<br>
+++ b/rational.c<br>
@@ -419,7 +419,7 @@ nurat_int_check(VALUE num)<br>
break;<br>
default:<br>
if (!k_numeric_p(num) || !f_integer_p(num))</p>
<ul>
<li>
<pre><code> rb_raise(rb_eArgError, "not an integer");
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> rb_raise(rb_eTypeError, "not an integer");
</code></pre>
}<br>
}<br>
=end</li>
</ul> Ruby master - Bug #2829 (Closed): Missing documentation for Exception subclasses.https://bugs.ruby-lang.org/issues/28292010-03-02T13:38:53Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
I noticed that the documentation for Exception subclasses are either that of Exception itself, or just plain non-sensical because they are actually missing (see ZeroDivisionError, FiberError, ...)</p>
<p>It would be preferable if the Exception classes were at least briefly described.</p>
<p>I've made a first draft of a description for all Exception subclasses, and would encourage anyone interested in improving it by editing the wiki:</p>
<p><a href="http://redmine.ruby-lang.org/wiki/ruby/ExceptionClassesDoc" class="external">http://redmine.ruby-lang.org/wiki/ruby/ExceptionClassesDoc</a></p>
<p>Thanks.<br>
=end</p> Ruby master - Feature #2772 (Closed): Matrix: Calculating determinant using Bareiss algorithm [pa...https://bugs.ruby-lang.org/issues/27722010-02-21T06:16:21Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Yu Ichino suggested to use a different algorithm to calculate the determinant of a matrix in <a href="https://blade.ruby-lang.org/ruby-core/28166">[ruby-core:28166]</a>.</p>
<p>I second his proposal. To reduce the risk of this proposal to go without a response, I am creating this request.</p>
<p>Bareiss' algorithm has two big advantages:</p>
<ul>
<li>can calculate the determinant of integer matrices using only integer intermediate results.</li>
<li>has minimal requirements on the number of bits required for intermediate results, thus reducing the floating point rounding errors.</li>
</ul>
<p>Performance-wise, it has the same complexity O(n^3) as the current traditional method.<br>
For Integer matrices, there is a big gain (say about 15 times faster) because the traditional version must use #quo and rationals, while the Bareiss algorithm can use #/ and keep the intermediate results as a Fixnum. The same goes for Bignum, of course (where the gain is even bigger).<br>
For float version, the Bareiss algorithm is slightly slower (~33%):</p>
<pre><code> user system total real
</code></pre>
<p>Fixnum: det 8.660000 0.010000 8.670000 ( 8.672686)<br>
Fixnum: det_bareiss 0.590000 0.000000 0.590000 ( 0.594747)<br>
Float: det 0.160000 0.000000 0.160000 ( 0.154779)<br>
Float: det_bareiss 0.240000 0.000000 0.240000 ( 0.237806)</p>
<p>I have revised Yu's code, and attached a patch.</p>
<p>I'm also attaching the performance test I used, for anyone interested.<br>
=end</p> Ruby master - Feature #2771 (Closed): Matrix: constructor to build with blockhttps://bugs.ruby-lang.org/issues/27712010-02-21T06:10:56Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
I believe the following simple constructor could be a helpful addition to matrix.rb</p>
<p>class Matrix</p>
<h1></h1>
<a name="Creates-a-matrix-of-row_size-x-column_size"></a>
<h1 >Creates a matrix of +row_size+ x +column_size+.<a href="#Creates-a-matrix-of-row_size-x-column_size" class="wiki-anchor">¶</a></h1>
<a name="It-fills-the-values-by-calling-the-given-block"></a>
<h1 >It fills the values by calling the given block,<a href="#It-fills-the-values-by-calling-the-given-block" class="wiki-anchor">¶</a></h1>
<a name="passing-the-current-row-and-column"></a>
<h1 >passing the current row and column.<a href="#passing-the-current-row-and-column" class="wiki-anchor">¶</a></h1>
<h1></h1>
<a name="m-Matrixbuild2-4-row-col-col-row-"></a>
<h1 >m = Matrix.build(2, 4) {|row, col| col - row }<a href="#m-Matrixbuild2-4-row-col-col-row-" class="wiki-anchor">¶</a></h1>
<a name="gt-Matrix0-1-2-3-1-0-1-2"></a>
<h1 >=> Matrix[[0, 1, 2, 3], [-1, 0, 1, 2]]<a href="#gt-Matrix0-1-2-3-1-0-1-2" class="wiki-anchor">¶</a></h1>
<a name="m-Matrixbuild3-rand-"></a>
<h1 >m = Matrix.build(3) { rand }<a href="#m-Matrixbuild3-rand-" class="wiki-anchor">¶</a></h1>
<a name="gt-a-3x3-matrix-with-random-elements"></a>
<h1 >=> a 3x3 matrix with random elements<a href="#gt-a-3x3-matrix-with-random-elements" class="wiki-anchor">¶</a></h1>
<h1></h1>
<p>def self.build(row_size, column_size = row_size)<br>
raise ArgumentError if row_size < 0 || column_size < 0<br>
return to_enum :build, row_size, column_size unless block_given?<br>
rows = row_size.times.map do |i|<br>
column_size.times.map do |j|<br>
yield i, j<br>
end<br>
end<br>
new rows, column_size<br>
end<br>
end<br>
=end</p> Ruby master - Bug #2770 (Closed): Matrix: determinant for rectangular matrices should raise an er...https://bugs.ruby-lang.org/issues/27702010-02-21T04:46:28Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Keiju,</p>
<p>$ rubydev -r matrix -e "puts Matrix[[1], [2], [3]].determinant"<br>
0</p>
<p>This corresponds to the documentation, but is not mathematically valid, since the determinant for rectangular matrices is not defined (at least for now! <a href="http://bit.ly/bwW7Gs" class="external">http://bit.ly/bwW7Gs</a> )</p>
<p>I believe an error should be thrown, similar to:<br>
$ rubydev -r matrix -e "puts Matrix[[1], [2], [3]].trace"<br>
/usr/local/rubydev/lib/ruby/1.9.1/matrix.rb:837:in <code>trace': Matrix dimension mismatch (ExceptionForMatrix::ErrDimensionMismatch) from -e:1:in </code>'</p>
<p>Since this is an API change, I attached a patch and will wait for your approval before committing.<br>
=end</p> Ruby master - Bug #2601 (Closed): BasicObject.initialize should raise an errorhttps://bugs.ruby-lang.org/issues/26012010-01-13T11:55:19Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
While having fun cloning BasicObject (see issue 2443), I found the amusing bug that :initialize could successfully be sent to BasicObject, creating all sorts of havoc.</p>
<p>$ rubydev -e "BasicObject.send :initialize; puts Object.ancestors" # => Loops indefinitely</p>
<p>$ rubydev -e "BasicObject.send :initialize, String; puts 42.upcase" # => Segmentation Fault</p>
<p>It was even possible to change the root of all Ruby classes without running into trouble:<br>
$ rubydev -e '<br>
SuperBasicObject = BasicObject.clone<br>
BasicObject.send :initialize, SuperBasicObject<br>
puts BasicObject.superclass<br>
'</p>
<a name="gt-SuperBasicObject"></a>
<h1 >==> SuperBasicObject<a href="#gt-SuperBasicObject" class="wiki-anchor">¶</a></h1>
<p>I fixed it, although changes might be required depending on the outcome of issue #2443.<br>
=end</p> Ruby master - Feature #2542 (Closed): URI lib should be updated to RFC 3986https://bugs.ruby-lang.org/issues/25422010-01-01T03:45:44Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
RFC 2396 has been obsolete for nearly 5 years now.</p>
<p>It was replaced by RFC 3986 which aims at clarifying aspects that were not previously clear.<br>
=end</p> Ruby master - Bug #2525 (Closed): URI#normalize incompletehttps://bugs.ruby-lang.org/issues/25252009-12-24T16:38:28Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
"<a href="hTTp://example.com/" class="external">hTTp://example.com/</a>" and "<a href="http://exa%4dple.com/" class="external">http://exa%4dple.com/</a>" should both be normalized to "<a href="http://example.com/" class="external">http://example.com/</a>" as per RFC 3986.</p>
<p>They currently are not and thus not considered ==.</p>
<p>Tests added to RubySpec<br>
=end</p> Backport187 - Backport #2519 (Closed): __method__ can return NULL (and therefore crash ruby)https://bugs.ruby-lang.org/issues/25192009-12-23T15:23:30Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
In Ruby 1.8.7 and latest 1.8.8:</p>
<p>$ cat ohoh.rb<br>
puts <strong>method</strong></p>
<p>$ ruby18dev -e "load 'ohoh.rb'"<br>
val (null) id 140734799802560/Users/work/test/ohoh.rb:1:in <code>to_s': NULL pointer given (ArgumentError) from /Users/work/test/ohoh.rb:1:in </code>puts'<br>
from /Users/work/test/ohoh.rb:1<br>
from -e:1:in `load'<br>
from -e:1</p>
<p>Doing <strong>method</strong>.inspect instead will crash Ruby<br>
=end</p> Ruby master - Feature #2509 (Rejected): Recursive freezing?https://bugs.ruby-lang.org/issues/25092009-12-21T12:50:56Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
I like freezing my constants, config files I read, etc... I believe it is the typical use case for #freeze.</p>
<p>In all theses cases, what I really want to do is freeze everything. There is often no easy way to do this (e.g. for config files), or else one must explicitly call freeze a bunch of times, like:</p>
<p>DEFAULT_SEND_FILE_OPTIONS = {<br>
:type => 'application/octet-stream'.freeze,<br>
:disposition => 'attachment'.freeze,<br>
}.freeze</p>
<p>It would be very nice if there was an easy way to freeze recursively arrays, hashes, etc...</p>
<p>A solution would be for #freeze to accept a level argument (similar to flatten, but the default being 1), or alternatively a boolean one (recursive = false).</p>
<p>Should I write a patch for this feature request?</p>
<p>Thanks,</p>
<p>Marc-André<br>
=end</p> Ruby master - Bug #2499 (Closed): InstructionSequence.dissassemble can crashhttps://bugs.ruby-lang.org/issues/24992009-12-19T11:52:54Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
I was trying to understand what InstructionSequence.disassemble is supposed to do when:</p>
<p>$ rubydev -e 'RubyVM::InstructionSequence.disassemble("x".method(:upcase))'<br>
-e:1: [BUG] Segmentation fault<br>
ruby 1.9.2dev (2009-12-19 trunk 26121) [x86_64-darwin10.2.0]</p>
<h2>-- control frame ----------<br>
c:0004 p:---- s:0010 b:0010 l:000009 d:000009 CFUNC :disassemble<br>
c:0003 p:0027 s:0006 b:0006 l:0022c8 d:001e98 EVAL -e:1<br>
c:0002 p:---- s:0004 b:0004 l:000003 d:000003 FINISH<br>
c:0001 p:0000 s:0002 b:0002 l:0022c8 d:0022c8 TOP</h2>
<p>-e:1:in <code><main>' -e:1:in </code>disassemble'</p>
<p>-- C level backtrace information -------------------------------------------</p>
<p>[NOTE]<br>
You may have encountered a bug in the Ruby interpreter or extension libraries.<br>
Bug reports are welcome.<br>
For details: <a href="http://www.ruby-lang.org/bugreport.html" class="external">http://www.ruby-lang.org/bugreport.html</a></p>
<p>Abort trap<br>
=end</p> Ruby master - Bug #2497 (Closed): Matrix: Vector#each2 with no block returns unusable enumeratorhttps://bugs.ruby-lang.org/issues/24972009-12-19T11:04:05Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Fixed in r26125<br>
=end</p> Ruby master - Bug #2496 (Closed): Delegate: #methods and #public_methods should return delegated ...https://bugs.ruby-lang.org/issues/24962009-12-19T10:38:20Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
require 'delegate'<br>
s = SimpleDelegator.new "Hello, world!"<br>
s.respond_to? :upcase # => true<br>
s.method :upcase # => #<Method : SimpleDelegator#upcase><br>
s.methods.include? :upcase # => false, true expected</p>
<p>Similar problem with public_methods.<br>
I propose that they return the union of methods from the delegator object and the methods of the object delegated to (only the public ones, since other ones are not forwarded)</p>
<p>Patch:<br>
diff --git a/lib/delegate.rb b/lib/delegate.rb<br>
index 77804e4..2fd5b49 100644<br>
--- a/lib/delegate.rb<br>
+++ b/lib/delegate.rb<br>
@@ -158,6 +158,22 @@ class Delegator<br>
end</p>
<pre><code>#
</code></pre>
<ul>
<li>
<a name="Returns-the-methods-available-to-this-delegate-object-as-the-union"></a>
<h1 >Returns the methods available to this delegate object as the union<a href="#Returns-the-methods-available-to-this-delegate-object-as-the-union" class="wiki-anchor">¶</a></h1>
</li>
<li>
<a name="of-this-objects-methods-and-the-public-methods-of-__getobj__"></a>
<h1 >of this object's methods and the public methods of __getobj__.<a href="#of-this-objects-methods-and-the-public-methods-of-__getobj__" class="wiki-anchor">¶</a></h1>
</li>
<li>
<h1></h1>
</li>
<li>def methods</li>
<li>self.<strong>getobj</strong>.public_methods | super</li>
<li>end</li>
<li>
<li>
<h1></h1>
</li>
<li>
<a name="Returns-the-methods-available-to-this-delegate-object-as-the-union-of-this-object"></a>
<h1 >Returns the methods available to this delegate object as the union of this object<a href="#Returns-the-methods-available-to-this-delegate-object-as-the-union-of-this-object" class="wiki-anchor">¶</a></h1>
</li>
<li>
<a name="and-the-methods-of-__getobj__"></a>
<h1 >and the methods of __getobj__.<a href="#and-the-methods-of-__getobj__" class="wiki-anchor">¶</a></h1>
</li>
<li>
<h1></h1>
</li>
<li>def public_methods(all=true)</li>
<li>self.<strong>getobj</strong>.public_methods(all) | super</li>
<li>end</li>
<li>
<li>
<h1></h1>
<a name="Returns-true-if-two-objects-are-considered-same"></a>
<h1 >Returns true if two objects are considered same.<a href="#Returns-true-if-two-objects-are-considered-same" class="wiki-anchor">¶</a></h1>
<h1></h1>
def ==(obj)<br>
=end</li>
</ul> Ruby master - Bug #2495 (Closed): Matrix: Vector#each2 should check its argumenthttps://bugs.ruby-lang.org/issues/24952009-12-19T10:35:22Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
$ rubydev -r matrix -e 'p Vector[*1..4].each2(nil){|x, y| p "#{x}, #{y}"}'<br>
/usr/local/rubydev/lib/ruby/1.9.1/matrix.rb:1149:in <code>each2': undefined method </code>size' for nil:NilClass (NoMethodError)</p>
<p>$ rubydev -r matrix -e 'p Vector[*1..4].each2(42){|x, y| p "#{x}, #{y}"}'<br>
/usr/local/rubydev/lib/ruby/1.9.1/matrix.rb:1149:in <code>each2': Vector dimension mismatch (ExceptionForMatrix::ErrDimensionMismatch) from -e:1:in </code>'</p>
<p>$ rubydev -r matrix -e 'p Vector[*1..8].each2(42){|x, y| p "#{x}, #{y}"}'<br>
"1, 0"<br>
"2, 1"<br>
"3, 0"<br>
"4, 1"<br>
"5, 0"<br>
"6, 1"<br>
"7, 0"<br>
"8, 0"</p>
<p>(or vice versa, if on a 32 bit platform)<br>
=end</p> Ruby master - Feature #2451 (Closed): BasicObject.initialize with variable number of argumenthttps://bugs.ruby-lang.org/issues/24512009-12-07T10:18:32Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
If one wants to write a class easily extensible (for some kind of library, say), then there is no nice way to have the initialize method be extensible other than through monkeypatching.</p>
<p>This could be made much more flexible if BasicObject.initialize accepted any number of arguments.</p>
<p>Would there be a downsize to have BasicObject.initialize accept many arguments?</p>
<p>Here's a more detailed example:</p>
<p>class NiceClass<br>
def initialize(arg1, arg2)<br>
# do some stuff with arg1 and arg2<br>
super # allow for included modules to initialize<br>
end<br>
end</p>
<a name="Someone-else"></a>
<h1 >Someone else:<a href="#Someone-else" class="wiki-anchor">¶</a></h1>
<p>class NiceClass<br>
module CoolExtension<br>
def initialize(arg1, arg2)<br>
# do cool stuff<br>
super # allow for more extensions<br>
end<br>
end</p>
<p>include CoolExtension<br>
end</p>
<p>This would not work unless BasicObject#initialize accepts any number of arguments. Currently, only super() -- i.e. passing none of the arguments -- can be called, so arg1 & arg2 must be copied to instance variables for included modules to access, or else monkeypatching becomes the only possibility.</p>
<p>The patch is trivial:</p>
<p>diff --git a/object.c b/object.c<br>
index 10eb983..33cae20 100644<br>
--- a/object.c<br>
+++ b/object.c<br>
@@ -2538,7 +2538,7 @@ Init_Object(void)<br>
#undef rb_intern<br>
#define rb_intern(str) rb_intern_const(str)</p>
<ul>
<li>rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, 0);</li>
</ul>
<ul>
<li>rb_define_private_method(rb_cBasicObject, "initialize", rb_obj_dummy, -1);<br>
rb_define_alloc_func(rb_cBasicObject, rb_class_allocate_instance);<br>
rb_define_method(rb_cBasicObject, "==", rb_obj_equal, 1);<br>
rb_define_method(rb_cBasicObject, "equal?", rb_obj_equal, 1);</li>
</ul>
<p>Notes:</p>
<ul>
<li>There is no documentation for BasicObject#initialize.</li>
<li>Ironically, the Ruby Draft Specification states that Object#initialize accepts any number of arguments! I'm glad I already have that team agree with me ;-)</li>
<li>No error is generated by make test-all</li>
<li>See also <a href="http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html" class="external">http://blog.rubybestpractices.com/posts/rklemme/018-Complete_Class.html</a> where Robert Klemme recommends calling super from constructors but has to use super(), i.e. passing no arguments</li>
</ul>
<p>Similarly, I also propose that Object#initialize accepts any number of arguments in Ruby 1.8.8<br>
=end</p> Backport187 - Backport #2450 (Closed): Array#sample can loop forever [patched]https://bugs.ruby-lang.org/issues/24502009-12-07T06:41:41Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
[:hello].sample(42) # ==> loops on Ruby 1.8.8</p>
<p>Fixed.</p>
<p>Other backports pass RubySpec.<br>
=end</p> Ruby master - Bug #2365 (Closed): Matrix: poor handling of coercion errors [patch]https://bugs.ruby-lang.org/issues/23652009-11-14T10:35:04Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
rubydev -r matrix -e 'p Matrix.I(2) - nil'<br>
/usr/local/rubydev/lib/ruby/1.9.1/matrix.rb:533:in <code>-': undefined method </code>coerce' for nil:NilClass (NoMethodError)<br>
from -e:1:in `'</p>
<p>Expected:<br>
some_where_in_the/matrix.rb:in <code>-': nil can't be coerced into Matrix (TypeError) from -e:1:in </code>'</p>
<p>Same situation with Vector.</p>
<p>I'd be grateful if you could confirm the attached patch is ok.<br>
=end</p> Backport186 - Backport #2364 (Closed): Float conversion of NaN in 1.8.xhttps://bugs.ruby-lang.org/issues/23642009-11-14T09:36:10Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Trying to fix issue <a class="issue tracker-4 status-5 priority-4 priority-default closed" title="Backport: lib/bigdecimal: errors in comparisons [patch] (Closed)" href="https://bugs.ruby-lang.org/issues/2349">#2349</a> for 1.8.8 but running into a small problem: conversion to a float will fail if the value converted corresponds to NaN:</p>
<p>$ ruby19 -r bigdecimal -e "p Float(BigDecimal('NaN'))"<br>
NaN<br>
$ ruby18 -r bigdecimal -e "p Float(BigDecimal('NaN'))"<br>
ArgumentError: invalid value for Float()</p>
<p>This is true of any class for which #to_f returns NaN.</p>
<p>This makes it impossible for BigDecimal("NaN") to be converted to a float in 1.8.</p>
<p>Can anyone think of a reason not to bring 1.8 inline with 1.9 (by allowing NaN)?</p>
<p>diff --git a/object.c b/object.c<br>
index 4704ebf..dd67039 100644<br>
--- a/object.c<br>
+++ b/object.c<br>
@@ -2486,13 +2486,7 @@ rb_Float(val)<br>
break;</p>
<pre><code> default:
</code></pre>
<ul>
<li>
<pre><code> {
</code></pre>
</li>
<li>
<pre><code> VALUE f = rb_convert_type(val, T_FLOAT, "Float", "to_f");
</code></pre>
</li>
<li>
<pre><code> if (isnan(RFLOAT(f)->value)) {
</code></pre>
</li>
<li>
<pre><code> rb_raise(rb_eArgError, "invalid value for Float()");
</code></pre>
</li>
<li>
<pre><code> }
</code></pre>
</li>
<li>
<pre><code> return f;
</code></pre>
</li>
<li>
<pre><code> }
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> return rb_convert_type(val, T_FLOAT, "Float", "to_f");
</code></pre>
}<br>
}</li>
</ul>
<p>(Doesn't generate any error in make test or test-all)<br>
=end</p> Backport186 - Backport #2349 (Closed): lib/bigdecimal: errors in comparisons [patch]https://bugs.ruby-lang.org/issues/23492009-11-09T15:33:34Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
$ ruby -r bigdecimal -e 'p BigDecimal.new("1") < nil'<br>
nil</p>
<p>expected: an error like with any other mathematical type:<br>
-e:1:in `<': comparison of BigDecimal with nil failed (ArgumentError)</p>
<hr>
<p>$ ruby -r bigdecimal -e 'p BigDecimal.new("1") == nil'<br>
nil</p>
<p>expected: false like with any other Ruby object</p>
<hr>
<p>$ ruby -r bigdecimal -e 'p BigDecimal.new("NaN") < 1'<br>
nil</p>
<p>expected: false, like with any other mathematical comparison</p>
<p>I'll commit the attached patch in a few days (for 1.8 & 1.9) unless there are arguments against it.<br>
=end</p> Ruby master - Feature #2347 (Closed): Math::INFINITYhttps://bugs.ruby-lang.org/issues/23472009-11-09T04:53:11Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
It is easy to get an infinity in Ruby (ex: 1.0/0) but that may not be obvious to everyone.</p>
<p>Could we have Math::INFINITY which would make code using it cleaner?</p>
<p>Thanks</p>
<p>diff --git a/math.c b/math.c<br>
index 51caf35..653a239 100644<br>
--- a/math.c<br>
+++ b/math.c<br>
@@ -764,6 +764,7 @@ Init_Math(void)<br>
#else<br>
rb_define_const(rb_mMath, "E", DBL2NUM(exp(1.0)));<br>
#endif</p>
<ul>
<li>
<p>rb_define_const(rb_mMath, "INFINITY", DBL2NUM(1.0/0.0));</p>
<p>rb_define_module_function(rb_mMath, "atan2", math_atan2, 2);<br>
rb_define_module_function(rb_mMath, "cos", math_cos, 1);<br>
=end</p>
</li>
</ul> Ruby master - Bug #2330 (Closed): Non systematic segmentation fault with autoload rubyspechttps://bugs.ruby-lang.org/issues/23302009-11-04T14:36:10Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Starting from r25601, the following rubyspec will crash about half of the time (just repeat a couple of times):</p>
<p>$ mspec -t rubydev core/kernel/autoload_spec.rb<br>
ruby 1.9.2dev (2009-11-04 trunk 25641) [x86_64-darwin10.0.0]<br>
.........../Users/work/mspec/lib/mspec/mocks/proxy.rb:8: [BUG] Segmentation fault<br>
ruby 1.9.2dev (2009-11-04 trunk 25641) [x86_64-darwin10.0.0]</p>
<p>-- control frame ----------<br>
c:0036 p:0024 s:0121 b:0121 l:000120 d:000120 METHOD /Users/work/mspec/lib/mspec/mocks/proxy.rb:8<br>
c:0035 p:---- s:0115 b:0115 l:000114 d:000114 FINISH<br>
c:0034 p:---- s:0113 b:0113 l:000112 d:000112 CFUNC :autoload<br>
c:0033 p:0057 s:0108 b:0108 l:000208 d:000107 BLOCK /Users/work/ruby/dev/spec/rubyspec/core/kernel/autoload_spec.rb:105<br>
c:0032 p:---- s:0105 b:0105 l:000104 d:000104 FINISH<br>
c:0031 p:---- s:0103 b:0103 l:000102 d:000102 CFUNC :instance_eval<br>
c:0030 p:0017 s:0100 b:0100 l:000099 d:000099 METHOD /Users/work/mspec/lib/mspec/runner/mspec.rb:67<br>
c:0029 p:0021 s:0094 b:0094 l:000081 d:000093 BLOCK /Users/work/mspec/lib/mspec/runner/context.rb:135<br>
c:0028 p:---- s:0091 b:0091 l:000090 d:000090 FINISH<br>
c:0027 p:---- s:0089 b:0089 l:000084 d:000088 IFUNC :instance_variable_get<br>
c:0026 p:---- s:0087 b:0087 l:000086 d:000086 CFUNC :each<br>
c:0025 p:---- s:0085 b:0085 l:000084 d:000084 CFUNC :all?<br>
c:0024 p:0053 s:0082 b:0082 l:000081 d:000081 METHOD /Users/work/mspec/lib/mspec/runner/context.rb:135<br>
c:0023 p:0101 s:0076 b:0076 l:000065 d:000075 BLOCK /Users/work/mspec/lib/mspec/runner/context.rb:163<br>
c:0022 p:---- s:0071 b:0071 l:000070 d:000070 FINISH<br>
c:0021 p:---- s:0069 b:0069 l:000068 d:000068 CFUNC :each<br>
c:0020 p:0127 s:0066 b:0066 l:000065 d:000065 METHOD /Users/work/mspec/lib/mspec/runner/context.rb:155<br>
c:0019 p:0109 s:0063 b:0063 l:000062 d:000062 METHOD /Users/work/mspec/lib/mspec/runner/mspec.rb:36<br>
c:0018 p:0029 s:0056 b:0056 l:000055 d:000055 METHOD /Users/work/mspec/lib/mspec/runner/object.rb:11<br>
c:0017 p:0167 s:0049 b:0049 l:000208 d:000208 TOP /Users/work/ruby/dev/spec/rubyspec/core/kernel/autoload_spec.rb:69<br>
c:0016 p:---- s:0047 b:0047 l:000046 d:000046 FINISH<br>
</p>
<p>mspec version: 1.5.12<br>
rubyspec: current<br>
=end</p> Ruby master - Bug #2311 (Closed): [BUG] cfp consistency error - sendhttps://bugs.ruby-lang.org/issues/23112009-10-30T12:15:55Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Following r25521:</p>
<p>$rubydev -e '<br>
class X<br>
def method_missing(s); end<br>
end<br>
X.new.foo(:bar) rescue nil<br>
puts "hello"<br>
'</p>
<p>Generates<br>
-e:0:in <code>method_missing': wrong number of arguments (2 for 1) (ArgumentError) from -e:5:in </code>'<br>
Instead of "hello"</p>
<p>$ mspec core/file/stat/directory_spec.rb -t rubydev<br>
crashes ruby with [BUG] cfp consistency error - send<br>
=end</p> Ruby master - Bug #2276 (Closed): Array#<=> should not raise when comparison failshttps://bugs.ruby-lang.org/issues/22762009-10-26T20:03:17Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Since the addition of Object#<=>, the only comparison that raised an error was Array#<=>(not_an_array).</p>
<p>Array#<=>(obj) now returns nil if obj is not array-like.</p>
<p>Maybe this should also be applied in the 1.8 line?</p>
<p>Note: neither test-all nor rubyspec were testing for this.<br>
=end</p> Ruby master - Feature #2266 (Closed): Matrix and Complex [patch]https://bugs.ruby-lang.org/issues/22662009-10-25T07:36:18Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Now that Ruby 1.9 has Complex as a builtin type, it would be interesting if Matrix provided the following instance methods:<br>
#conj, alias conjugate<br>
#imag, alias imaginary<br>
#real,<br>
#real?,<br>
#rect, alias rectangular</p>
<p>Corresponding patch attached.</p>
<p>This patch could also be part of mathn in the ruby 1.8 branch.<br>
=end</p> Ruby master - Feature #2265 (Closed): Matrix#empty? [patch]https://bugs.ruby-lang.org/issues/22652009-10-25T07:33:01Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Now that the Matrix library handles well empty matrices, how about a new instance method #empty?</p>
<p>diff --git a/lib/matrix.rb b/lib/matrix.rb<br>
index b577ef3..45ef25e 100644<br>
--- a/lib/matrix.rb<br>
+++ b/lib/matrix.rb<br>
@@ -386,6 +386,14 @@ class Matrix<br>
#++</p>
<pre><code>#
</code></pre>
<ul>
<li>
<a name="Returns-true-if-this-is-an-empty-matrix-ie-if-the-number-of-rows"></a>
<h1 >Returns +true+ if this is an empty matrix, i.e. if the number of rows<a href="#Returns-true-if-this-is-an-empty-matrix-ie-if-the-number-of-rows" class="wiki-anchor">¶</a></h1>
</li>
<li>
<a name="or-the-number-of-columns-is-0"></a>
<h1 >or the number of columns is 0.<a href="#or-the-number-of-columns-is-0" class="wiki-anchor">¶</a></h1>
</li>
<li>
<h1></h1>
</li>
<li>def empty?</li>
<li>column_size == 0 || row_size == 0</li>
<li>end</li>
<li>
<li>
<h1></h1>
<a name="Returns-true-if-this-is-a-regular-matrix"></a>
<h1 >Returns +true+ if this is a regular matrix.<a href="#Returns-true-if-this-is-a-regular-matrix" class="wiki-anchor">¶</a></h1>
<h1></h1>
</li>
</ul>
<p>def regular?<br>
@@ -924,7 +932,7 @@ class Matrix</p>
<a name="Overrides-Objectto_s"></a>
<h1 >Overrides Object#to_s<a href="#Overrides-Objectto_s" class="wiki-anchor">¶</a></h1>
<h1></h1>
<p>def to_s</p>
<ul>
<li>if row_size == 0 || column_size == 0</li>
</ul>
<ul>
<li>if empty?<br>
"Matrix.empty(#{row_size}, #{column_size})"<br>
else<br>
"Matrix[" + @rows.collect{|row|<br>
@@ -939,7 +947,7 @@ class Matrix</li>
</ul>
<a name="Overrides-Objectinspect"></a>
<h1 >Overrides Object#inspect<a href="#Overrides-Objectinspect" class="wiki-anchor">¶</a></h1>
<h1></h1>
<p>def inspect</p>
<ul>
<li>if row_size == 0 || column_size == 0</li>
</ul>
<ul>
<li>if empty?<br>
"Matrix.empty(#{row_size}, #{column_size})"<br>
else<br>
"Matrix#{@rows.inspect}"<br>
=end</li>
</ul> Ruby 1.8 - Backport #2261 (Closed): lib/matrix: following the extensive changeshttps://bugs.ruby-lang.org/issues/22612009-10-24T15:33:53Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
(a) Shouldn't r25412 (and other related commits) be also applied to the 1.8 branch?</p>
<p>(b) r25412 introduced Matrix#inspect_org. It is not documented.</p>
<p>Its output relies on the way the matrix information is stored internally by the Matrix class. Shouldn't this be considered implementation details and thus subject to change and not for public consumption?</p>
<p>It should either:</p>
<ul>
<li>be removed,</li>
<li>be made private (although it is not used by the implementation) or</li>
<li>be documented</li>
</ul>
<p>I recommend the first option</p>
<p>(c) #compare_by_row_vectors and #compare_by should either:</p>
<ul>
<li>be removed (they are not used by the implementation anymore),</li>
<li>be made private or</li>
<li>be documented.</li>
</ul>
<p>I recommend the first option<br>
=end</p> Ruby master - Bug #2224 (Closed): lib/delegate: operator delegationhttps://bugs.ruby-lang.org/issues/22242009-10-17T13:15:20Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The operators ==, =~, !~ are forwarded by Delegate. I presume the operators != and ~, new in 1.9, have simply been forgotten?</p>
<p>As for eql? and hash, this is probably intentional. I am still curious as to why, since this can yield surprising results (at least to me):</p>
<p>a = "foo"<br>
a1 = SimpleDelegator.new(a)<br>
a2 = a1.dup<br>
h = {}<br>
h[a] = :bar<br>
h[a1] = :bar<br>
h[a2] = :bar<br>
h # ==> {"foo"=>:bar, "foo"=>:bar, "foo"=>:bar}<br>
=end</p> Ruby master - Bug #2223 (Closed): lib/delegate: security model?https://bugs.ruby-lang.org/issues/22232009-10-17T12:39:33Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Take the following code:</p>
<p>require 'delegate'<br>
cat = "cat"<br>
dog = SimpleDelegator.new("dog")</p>
<p>cat.untrust<br>
dog.untrust</p>
<p>lambda {$SAFE = 4; cat.upcase!}.call # ==> "CAT"<br>
lambda {$SAFE = 4; dog.upcase!}.call # ==> Security Error</p>
<p>Is that expected?</p>
<p>Maybe #trust, #untrust, #taint and #untaint should both call 'super' and forward the call to <strong>getobj</strong>?</p>
<p>I'm even less sure as to what to do with #tainted? and #untrusted? for mixed cases (i.e. when self and <strong>getobj</strong> have different taintedness/trust). Disallow these cases? return "super || <strong>getobj</strong>.tainted?" ?<br>
=end</p> Ruby master - Bug #2222 (Closed): Regex creation error in safe modehttps://bugs.ruby-lang.org/issues/22222009-10-17T11:58:25Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
$ ruby -e '$SAFE=4; /#{}/o'<br>
-e:1:in `': Insecure: can't modify array (SecurityError)</p>
<p>Fairly recent since error not present in ruby 1.9.2dev (2009-08-30 trunk 24705)<br>
=end</p> Ruby master - Bug #2221 (Closed): lib/delegate: freeze has odd effectshttps://bugs.ruby-lang.org/issues/22212009-10-16T15:43:36Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Freeze doesn't quite freeze, and can't be cloned:</p>
<p>require 'delegate'<br>
d = SimpleDelegator.new([1,2,3])<br>
d.freeze<br>
d[0] = :hello; d # ==> [:hello, 2, 3], I expected a runtime error<br>
d.clone # ==> RuntimeError, I expected some kind of copy of d</p>
<p>Maybe #freeze and #frozen should be forwarded:</p>
<p>diff --git a/lib/delegate.rb b/lib/delegate.rb<br>
index 57c479c..f4bd453 100644<br>
--- a/lib/delegate.rb<br>
+++ b/lib/delegate.rb<br>
@@ -115,7 +115,7 @@</p>
<a name="implementation-see-SimpleDelegator"></a>
<h1 >implementation, see SimpleDelegator.<a href="#implementation-see-SimpleDelegator" class="wiki-anchor">¶</a></h1>
<h1></h1>
<p>class Delegator</p>
<ul>
<li>[:to_s,:inspect,:=~,:!~,:===].each do |m|</li>
</ul>
<ul>
<li>[:to_s,:inspect,:=~,:!~,:===, :freeze, :frozen?].each do |m|<br>
undef_method m<br>
end</li>
</ul>
<p>But maybe the Delegator itself should also be frozen? I mean should a call to #<strong>setobj</strong> raise a runtime error or not?</p>
<p>Also, there are other methods that should probably be forwarded (eql?, hash, etc...); see issue <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Delegator < BasicObject (Rejected)" href="https://bugs.ruby-lang.org/issues/1333">#1333</a>.<br>
=end</p> Ruby master - Bug #2207 (Closed): lib/delegate: #method doesn't delegate to its objecthttps://bugs.ruby-lang.org/issues/22072009-10-14T13:45:55Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
require 'delegate'<br>
d = SimpleDelegator.new("hello")<br>
d.method(:upcase) # ==> NameError: undefined method <code>upcase' for class </code>SimpleDelegator'</p>
<p>Note that in Ruby 1.8, this does not create an error.<br>
This is fixed by defining respond_to_missing? instead of respond_to?</p>
<p>diff --git a/lib/delegate.rb b/lib/delegate.rb<br>
index 57c479c..6b9f91a 100644<br>
--- a/lib/delegate.rb<br>
+++ b/lib/delegate.rb<br>
@@ -143,12 +143,11 @@ class Delegator<br>
end</p>
<pre><code>#
</code></pre>
<ul>
<li>
<a name="Checks-for-a-method-provided-by-this-the-delegate-object-by-fowarding-the"></a>
<h1 >Checks for a method provided by this the delegate object by fowarding the<a href="#Checks-for-a-method-provided-by-this-the-delegate-object-by-fowarding-the" class="wiki-anchor">¶</a></h1>
</li>
</ul>
<ul>
<li>
<a name="Checks-for-a-method-provided-by-this-the-delegate-object-by-forwarding-the"></a>
<h1 >Checks for a method provided by this the delegate object by forwarding the<a href="#Checks-for-a-method-provided-by-this-the-delegate-object-by-forwarding-the" class="wiki-anchor">¶</a></h1>
<a name="call-through-__getobj__"></a>
<h1 >call through __getobj__.<a href="#call-through-__getobj__" class="wiki-anchor">¶</a></h1>
<h1></h1>
</li>
</ul>
<ul>
<li>def respond_to?(m, include_private = false)</li>
<li>return true if super</li>
<li>return self.<strong>getobj</strong>.respond_to?(m, include_private)</li>
</ul>
<ul>
<li>def respond_to_missing?(m, include_private = false)</li>
<li>
<strong>getobj</strong>.respond_to?(m, include_private)<br>
end</li>
</ul>
<pre><code>#
</code></pre>
<p>Only caveat is that after a change of object of different class, the method can produce a NoMethodError when called. (same as Ruby 1.8)<br>
Any objection?<br>
=end</p> Ruby master - Bug #2206 (Closed): lib/delegate: inconsistency between respond_to? and sendhttps://bugs.ruby-lang.org/issues/22062009-10-14T13:06:05Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
require 'delegate'<br>
class A<br>
private<br>
def private_method<br>
:bar<br>
end<br>
end</p>
<p>x = SimpleDelegator.new(A.new)<br>
x.respond_to?(:private_method, true) # ==> true<br>
x.send(:private_method) # ==> NoMethodError</p>
<p>I expected the call to private_method to be delegated. The attached patch fixes the problem. It is not very elegant but I couldn't think of anything better.<br>
=end</p> Ruby master - Bug #2199 (Closed): Object#method should call respond_to_missing?(sym, true)https://bugs.ruby-lang.org/issues/21992009-10-13T14:16:43Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Is there any reason I'm missing?</p>
<p>class A<br>
def respond_to_missing?(method, private = false)<br>
method == :is_private && private<br>
end</p>
<pre><code> def is_private2
end
private :is_private2
</code></pre>
<p>end</p>
<p>A.new.method(:is_private2) # ==> #<Method: A#is_private2>...<br>
A.new.method(:is_private) # ==> NameError: undefined method <code>is_private' for class </code>A'</p>
<p>If not:</p>
<p>diff --git a/proc.c b/proc.c<br>
index 5ed3c01..b7c632c 100644<br>
--- a/proc.c<br>
+++ b/proc.c<br>
@@ -902,7 +902,7 @@ mnew(VALUE klass, VALUE obj, ID id, VALUE mclass, int scope)<br>
VALUE sym = ID2SYM(id);</p>
<pre><code> if (obj != Qundef && !rb_method_basic_definition_p(klass, rmiss)) {
</code></pre>
<ul>
<li>
<pre><code> if (RTEST(rb_funcall(obj, rmiss, 1, sym))) {
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> if (RTEST(rb_funcall(obj, rmiss, 2, sym, Qtrue))) {
def = ALLOC(rb_method_definition_t);
def->type = VM_METHOD_TYPE_MISSING;
def->original_id = id;
</code></pre>
</li>
</ul>
<p>=end</p> Ruby master - Bug #2189 (Closed): Math.atanh(1) & Math.atanh(-1) should not raise an errorhttps://bugs.ruby-lang.org/issues/21892009-10-10T14:53:28Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Regression caught by RubySpec.</p>
<p>$ rubydev -v -e 'p Math.atanh(1)'<br>
ruby 1.9.2dev (2009-10-09 trunk 25274) [x86_64-darwin10.0.0]<br>
-e:1:in <code>atanh': Numerical argument out of domain - atanh (Errno::EDOM) from -e:1:in </code>'<br>
$ ruby187 -v -e 'p Math.atanh(1)'<br>
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]<br>
Infinity</p>
<p>Fixed in r25279<br>
=end</p> Ruby master - Bug #2173 (Closed): rake missing rake/contrib/*https://bugs.ruby-lang.org/issues/21732009-10-03T15:53:08Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Builtin rake is missing components that were part of the gem.</p>
<p>ruby187 -v -e "require 'rubygems'; require 'rake'; p require 'rake/contrib/sshpublisher'"<br>
ruby 1.8.7 (2008-08-11 patchlevel 72) [universal-darwin10.0]<br>
true</p>
<p>ruby19 -v -e "require 'rubygems'; require 'rake'; p require 'rake/contrib/sshpublisher'"<br>
ruby 1.9.2dev (2009-08-30 trunk 24705) [i386-darwin10.0.0]<br>
-e:1:in <code>require': no such file to load -- rake/contrib/sshpublisher (LoadError) from -e:1:in </code>'</p>
<p>This affects, among others, some popular gems (some of which have been fixed, others not). Unless there's a compelling reason not to, the contrib rake tasks should be included in core.<br>
=end</p> Ruby master - Feature #2172 (Closed): Enumerable#chunk with no blockhttps://bugs.ruby-lang.org/issues/21722009-10-03T13:48:45Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
What should "(1..3).chunk" (i.e. without a block) do?</p>
<p>It issued an<br>
ArgumentError: tried to create Proc object without a block</p>
<p>I changed the error message to "no block given" which I hope to be more informative, but maybe there is something more useful to do here?</p>
<p>A default block of {|x| x} doesn't seem all that useful.</p>
<p>Returning an enumerator that, upon completion, will return an enumerator would probably be better, but could also be a bit confusing if someone doesn't realize he forgot to specify the block?</p>
<p>Thanks to Run Paint for raising the question when writing the rubyspec for #chunk.<br>
=end</p> Ruby master - Bug #2140 (Closed): Bignum#** broken by lib/mathnhttps://bugs.ruby-lang.org/issues/21402009-09-24T09:37:35Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
ruby -r mathn -e 'p (1<<66)**2'<br>
/usr/local/ruby19/lib/ruby/1.9.1/mathn.rb:50:in <code>**': undefined method </code>power!' for 73786976294838206464:Bignum (NoMethodError)<br>
from -e:1:in `'</p>
<p>Fixed in r25067<br>
=end</p> Ruby 1.8 - Bug #2107 (Closed): Matrix: 1/any_matrix bug (fixed)https://bugs.ruby-lang.org/issues/21072009-09-17T13:43:19Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin</p>
<blockquote>
<p>ruby -r matrix -e "p 1/Matrix<a class="wiki-page new" href="https://bugs.ruby-lang.org/projects/ruby-18/wiki/1">1</a>"</p>
</blockquote>
<p>/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/matrix.rb:931:in <code>/': undefined local variable or method </code>_M' for #<Matrix::Scalar:0x1001199b8 @value=1> (NameError)<br>
from -e:1</p>
<p>Fixed in revision 24953</p>
<p><a href="http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24953" class="external">http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=24953</a><br>
=end</p> Ruby master - Bug #1885 (Closed): Proper comparison of recursive Struct & Rangehttps://bugs.ruby-lang.org/issues/18852009-08-05T05:30:15Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The following code freezes the latest ruby 1.9:</p>
<p>MyClass = Struct.new(:foo)<br>
x = MyClass.new; x[:foo] = x<br>
y = MyClass.new; y[:foo] = y<br>
x == y # Loops forever (can not be interrupted)</p>
<p>Solution: rb_struct_equal & rb_struct_eql should handle recursion in a similar fashion as Array and Hash (i.e. by calling rb_exec_recursive_paired and returning Qtrue if recursion is detected). I could make a patch if needed.</p>
<p>Searching the source code for rb_exec_recursive revealed that Range is potentially recursive too (see range_inspect). The ==, eql? and === methods do not call rb_exec_recursive_paired and are thus also potentially troublesome. To build a recursive Range is not trivial though; either some intermediate container class is needed or else some crazy thing like:</p>
<p>class CrazyRange < Range<br>
def initialize<br>
super(self..self)<br>
end</p>
<pre><code> def <=>(x)
0 # Needed so CrazyRange can be the begin and end values of a range...
end
</code></pre>
<p>end</p>
<p>CrazyRange.new == CrazyRange.new # Loops forever (can not be interrupted)</p>
<p>I'm not sure that it is worth modifying ==, eql? and === to use rb_exec_recursive_paired and make them bulletproof.</p>
<p>Note that both Struct#hash and Range#hash face the same issue than Array#hash & Hash#hash (see issue <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Enumerable's #hash Raises ArgumentError When Recursive Values are Present (Closed)" href="https://bugs.ruby-lang.org/issues/1852">#1852</a>)<br>
=end</p> Ruby master - Feature #1697 (Closed): Object#<=>https://bugs.ruby-lang.org/issues/16972009-06-28T10:48:38Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The definition of the <=> operator states:<br>
"... And if the two operands are not comparable, it returns nil" (The Ruby Programming Language, O'Reilly)</p>
<p>Attempting to compare objects, when one or both do not define the <=> operator, causes a NoMethodError to be raised. For example, "false <=> 0" raises in this way. This behavior is unexpected and runs counter to the principle defined above.</p>
<p>Further, "0 <=> false" returns nil. This is fundamentally inconsistent. The two comparisons are the other's converse, yet the raising of an exception in the first case implies that the programmer was in error; that the mere act of making this comparison was erroneous.</p>
<p>The solution is for Object to define a <=> operator. This will solve the case described above, along with the general case of comparing an object to another when one or both do not define <=>. Similarly to Time#<=>, it would return the converse of arg <=> self (i.e. nil => nil, num => -num). It needs to detect recursion, in which case it should return nil or 0 depending on the result of self == arg.</p>
<p>This change would make it always safe to call <=> without having to check first if it respond_to? :<=> (or rescuing NoMethodError).</p>
<p>The existence of Object#<=> would make it much easier for all programmers to define a good <=> operator for their classes. They can simply call super if they don't know how to handle some argument type. For example:</p>
<p>class MyClass<br>
include Comparable<br>
def <=> (arg)<br>
return super unless arg.is_a? MyClass<br>
# go on with comparison<br>
end<br>
end</p>
<p>With this simple line, the developper has enabled other classes to be comparable with MyClass. No need to monkeypatch MyClass to ensure that comparing its objects with objects of class ComparableToMyClass will work. Without a 'super', implementing this becomes quite difficult and requires the use of recursion guards (which are not defined in the standard library).</p>
<p>Note that neither String#<=> nor Time#<=> currently use recursion guards, which is not robust and can lead to problems. For instance:</p>
<p>class MyClass<br>
include Comparable<br>
def <=> (arg)<br>
return -1 if arg.is_a? MyClass<br>
cmp = arg <=> self<br>
cmp ? -cmp : nil<br>
end<br>
end</p>
<p>MyClass.new <=> Time.now</p>
<a name="gt-raises-a-SystemStackError"></a>
<h1 >==> raises a SystemStackError<a href="#gt-raises-a-SystemStackError" class="wiki-anchor">¶</a></h1>
<p>class Time<br>
alias_method :to_str, :to_s<br>
end<br>
"now" <=> Time.now</p>
<a name="gt-endless-loop-that-cant-be-interrupted-with-ctrl-C"></a>
<h1 >==> endless loop that can't be interrupted with ctrl-C.<a href="#gt-endless-loop-that-cant-be-interrupted-with-ctrl-C" class="wiki-anchor">¶</a></h1>
<p>In summary, defining Object#<=> would:</p>
<ol>
<li>bring consistency between a <=> b and b <=> a</li>
<li>provide a sensible default (nil) for objects that can't be compared</li>
<li>make it easier for generic methods to call <=> (no rescue or :respond_to? needed)</li>
<li>make it much easier for developpers to write extensible <=> methods for their classes.</li>
</ol>
<p>Side notes:</p>
<p>The proposition stands only for Object. BasicObject would still be available for developers preferring a class with a strict minimum of methods.</p>
<p>The only code that could break would have to be both checking respond_to? :<=> (or rescuing a NoMethodError) <em>and</em> behaving differently than if the <=> method had returned nil. Such code would be quite nonsensical, given the definition of <=></p>
<p>Other comparison operators like <, <=, >=, > would also gain in consistency if they were defined in terms of <=>. This way, 0 < nil and nil > 0 would raise the same errors instead of errors of different types. This is secondary to the main question: is it better to define Object#<=> or not?<br>
My vote is on 'yes'.</p>
<p>(Thanks to the readers of my first draft)<br>
=end</p> Ruby master - Bug #1686 (Closed): Enumerable#first brokenhttps://bugs.ruby-lang.org/issues/16862009-06-25T03:25:09Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Enumerable#first is broken in the current HEAD. If 4 <= n < enum_length + 4, enum.first(n) returns the (n-4)th element instead of an array of n elements. E.g.:</p>
<p>to6 = (1..6).to_enum # necessary so Enumerable#first is used<br>
p to6.first(2) # ==> [1, 2]<br>
p to6.first(4) # ==> 1<br>
p to6.first(9) # ==> 6<br>
p to6.first(10) # ==> [1, 2, 3, 4, 5, 6]</p>
<p>This is due to <a href="http://redmine.ruby-lang.org/repositories/diff/ruby-19/enum.c?rev=23622" class="external">http://redmine.ruby-lang.org/repositories/diff/ruby-19/enum.c?rev=23622</a> , after which ary[0] holds "n" as a long instead of a Fixnum. The comparison to Qnil isn't working as desired.</p>
<p>Either ary[0] holds INT2NUM(len) and first_i calls NUM2LONG + INT2NUM (as per my original patch, see <a href="http://redmine.ruby-lang.org/issues/show/1554" class="external">http://redmine.ruby-lang.org/issues/show/1554</a> ) or alternatively, enum_first could use take_i or enum_take when there is an argument, since they behave the same way in that case.<br>
=end</p> Ruby master - Feature #1667 (Closed): IO#codepoints, IO#each_codepoint, and StringIOhttps://bugs.ruby-lang.org/issues/16672009-06-20T21:47:52Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Almost all "iterators" of <code>String</code> are present in <code>IO</code> and <code>StringIO</code>: <code>#each_char</code>, <code>#each_byte</code>, <code>#each_line</code> and their corresponding <code>#chars</code>, <code>#bytes</code>, <code>#lines</code>. Only <code>#each_codepoint</code> and <code>#codepoints</code> are not defined in <code>IO</code> and <code>StringIO</code>.</p>
<p>Unless there is a compelling reason not to, it would be useful if these were defined. This would mirror the coherence with all other <code>each_</code>* methods that exist in both <code>String</code>, <code>IO</code> and <code>StringIO</code>.</p> Ruby master - Bug #1666 (Closed): Confusion in documentation for lines vs each_line, etc...https://bugs.ruby-lang.org/issues/16662009-06-20T21:44:22Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Currently, IO#lines is defined as "to_enum(:each_line, *args)" and thus will ignore a block if one is given.<br>
On the other hand, String#lines and String#each_line are aliases, and thus will both execute the block, if one given. The same is true for StringIO#lines and StringIO#each_line.</p>
<p>The same distinction exist in IO for #bytes vs #each_byte, #chars vs #each_char, while these pairs are aliases in String and StringIO.</p>
<p>To add to the confusion, the documentation is different for String#lines vs String#each_line, #bytes vs #each_byte, #chars vs #each_char (although they are aliases). StringIO#bytes, #lines & #chars are not documented at all.</p>
<p>So either:</p>
<ol>
<li>there should not be a distinction (and IO's implementation and doc should be changed to reflect that)<br>
or 2) the distinction is intentional (and String + StringIO's implementation should be changed to relect that)<br>
or 3) there is a compelling reason why the behavior in IO should be different than in String and StringIO and that should be spelled out in the doc.</li>
</ol>
<p>In all cases, the documentation for String should be cleaned up; for example String#each_char doesn't state that an enumerator is returned if no block is given (contrary to the doc for String#chars) and the examples are wrong since they use #each (which no longer exists) instead of #each_char.</p>
<p>Finally, the pair #codepoints and #each_codepoint is in a similar mismatch of documentation in String. I'll post a separate feature request to add IO#codepoints, etc...<br>
=end</p> Ruby master - Bug #1665 (Closed): Enumerable#reverse_each, #entries, #to_a documentation [patch]https://bugs.ruby-lang.org/issues/16652009-06-20T20:40:16Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The following are missing from the 1.8.7 release News:<br>
Enumerable#reverse_each (new method)<br>
Enumerable#to_a, #entries (takes optional arguments)</p>
<p>Since the 1.9 release News refer to the 1.8.7 news, this fixes both 1.8.7 and 1.9 release news.</p>
<p>Moreover the documentation for Enumerable#to_a, #entries needs to be updated in both the 1.8.7 and 1.9 releases (patches for both included).<br>
=end</p> Ruby master - Bug #1664 (Closed): Kernel#define_singleton_method not documented [patch]https://bugs.ruby-lang.org/issues/16642009-06-20T19:58:49Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Kernel#define_singleton_method is currently missing its documentation.<br>
I propose the following:</p>
<p>call-seq:<br>
define_singleton_method(symbol, method) => new_method<br>
define_singleton_method(symbol) { block } => proc</p>
<p>Defines a singleton method in the receiver. The <em>method</em><br>
parameter can be a +Proc+ or +Method+ object.<br>
If a block is specified, it is used as the method body. This block<br>
is evaluated using <code>instance_eval</code>.</p>
<pre><code>class A
class << self
def class_name
to_s
end
end
end
A.define_singleton_method(:who_am_i) do
"I am: #{class_name}"
end
A.who_am_i # ==> "I am: A"
guy = "Bob"
guy.define_singleton_method(:hello) { "#{self}: Hello there!" }
guy.hello # => "Bob: Hello there!"
</code></pre>
<p>I've included the corresponding patch. This method should also be documented in the 1.8.7 branch.<br>
=end</p> Ruby master - Bug #1663 (Closed): Small documentation fixes [patch]https://bugs.ruby-lang.org/issues/16632009-06-20T19:53:49Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
This patch improves the documentation for:<br>
String#partition, String#rpartition (argument can be regexp)<br>
Module#<=> (for modules without relationship, returns nil, not -1)<br>
Range#==, Struct.new, Array#hash: typos</p>
<p>These should be backported to the 1.8 branch.<br>
=end</p> Ruby master - Bug #1554 (Closed): Enumerator#first & #take should consume only what is needed [pa...https://bugs.ruby-lang.org/issues/15542009-06-02T05:38:59Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Currently, in Ruby 1.9.x:</p>
<p>require 'stringio'<br>
s = StringIO.new("first \n second \n third")</p>
<p>s.rewind<br>
p s.take(1), s.take(1)</p>
<a name="Prints-first-n-and-second-n"></a>
<h1 >Prints "[first \n]" and "[ second \n]"<a href="#Prints-first-n-and-second-n" class="wiki-anchor">¶</a></h1>
<p>s.rewind<br>
p [s.first], [s.first]</p>
<a name="Prints-first-n-and-second-n-2"></a>
<h1 >Prints "[first \n]" and "[ second \n]"<a href="#Prints-first-n-and-second-n-2" class="wiki-anchor">¶</a></h1>
<p>s.rewind<br>
p s.first(1), s.first(1)</p>
<a name="Prints-first-n-and-third"></a>
<h1 >Prints "[first \n]" and "[third]"<a href="#Prints-first-n-and-third" class="wiki-anchor">¶</a></h1>
<p>I believe most people would expect that [s.first], s.first(1) and s.take(1) should be the same and have the same side effects, if any. It is also more efficient that :each yields just the right number of times necessary to complete the request. As such it would be preferable if the last printout was the same as the previous two.</p>
<p>Note that in Ruby 1.8.7, the output for Enumerable#take is also wrong.</p>
<p>The included patches fix this issue for both versions.</p>
<p>I took the opportunity to change #first so that it calls :to_int on its argument only once if it needs to be converted. Before the patch it is called twice. This brings it in line with Array#first and Enumerable#take.</p>
<p>Note: rubyspecs have been updated.<br>
=end</p> Ruby master - Bug #1532 (Closed): Improved matrix.rb [patch]https://bugs.ruby-lang.org/issues/15322009-05-29T04:18:55Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The fact that the 'matrix' library is included in Ruby is very helpful.<br>
There are currently some open bugs, and some improvements could make it easier to use.</p>
<p>Propositions:</p>
<ol>
<li>Matrix#trace should raise an ErrDimensionMismatch if the matrix is not square</li>
</ol>
<p>Mathematically speaking, the trace is only defined for square matrices (ref: wikipedia, mathworld)<br>
Currently, Matrix[[1,2]].trace raises a NoMethodError: undefined method `[]' for nil:NilClass<br>
Note that Matrix[[1,2]].transpose.trace returns 1, although in mathematically, trace(M) = trace(transpose(M))</p>
<p>Raising an ErrDimensionMismatch would bring #trace in line with #inverse</p>
<ol start="2">
<li>Matrix creation methods should perform checks and conversion so that values are stored as an Array of Arrays.</li>
</ol>
<p>Currently, no checking is done, so the following will all be constructed without an error or a warning:<br>
Matrix[:hello]<br>
Matrix[nil]<br>
Matrix[4], etc...</p>
<p>Later on, confusing results or strange errors will happen. E.g.:<br>
Matrix[42].transpose # ==> Matrix[[42], [0], [0], [0]]</p>
<p>A TypeError should be raised if the argument is not convertible to an Array of Arrays.</p>
<p>Moreover, non arrays that should be converted using :to_ary, to be consistent<br>
with the builtin library methods that accept array arguments (e.g. Array#transpose)</p>
<p>Finally, conversion from Vector to arrays should be always be performed. Currently,<br>
a = Matrix[[1,2],[3,4]] # => Matrix[[1, 2], [3, 4]]<br>
b = Matrix.rows([a.row(0), a.row(1)]) # => Matrix[Vector[1, 2], Vector[3, 4]]<br>
a == b # => false<br>
It would be more useful, intuitive and mathematically correct if a == b and b.to_s == "Matrix[[1, 2], [3, 4]]"</p>
<p>The same is true for Vector creation methods. For example currently:<br>
Vector.elements(42, false).size # ==> 4<br>
Vector.elements(Vector[1,2,3]) == Vector.elements([1,2,3]) # ==> false<br>
It would be more useful, intuitive and correct if the first example raises an error and the second returns true</p>
<ol start="3">
<li>Matrix creators should enforce that a matrix is rectangular.</li>
</ol>
<p>Currently, a matrix with irregular rows can be created, e.g. x = Matrix[[1,2],[3]].<br>
Mathematically speaking, that is not a matrix.<br>
Basically none of the Matrix methods are of any use for non-rectangular matrices.<br>
Moreover, many strange errors can occur later on. For example, x.inverse will<br>
raise a "NoMethodError: undefined method `*' for nil:NilClass"</p>
<p>It would be helpful to catch these cases at creation time.<br>
Many creation methods don't have to make any extra checks (e.g. Matrix.scalar), and<br>
all methods of Matrix can bypass this extra check when they have created the arrays themselves<br>
(e.g. Matrix#*). There would be a small cost for creation using Matrix.[] and Matrix.rows,<br>
although it is in O(rows) while most other operations are usually in O(rows x columns),<br>
so the performance difference would be minimal.</p>
<ol start="4">
<li>Matrix should deal with empty matrices.</li>
</ol>
<p>Currently, empty matrices like Matrix[] cause problem.<br>
For example Matrix[].determinant raises an error, so does Matrix[] * Matrix[].</p>
<p>Moreover, if h = Matrix[[], []], then currently h.transpose.transpose != h</p>
<p>While an alternative would be to raise and error, the best solution is to handle<br>
empty matrices properly, both 0x0, 0xn and nx0, as does MatLab, GNU Octave, etc...<br>
See doc and references to the literature in:<br>
<a href="http://www.gnu.org/software/octave/doc/interpreter/Empty-Matrices.html" class="external">http://www.gnu.org/software/octave/doc/interpreter/Empty-Matrices.html</a></p>
<ol start="5">
<li>Out of bound indices should be dealt with.</li>
</ol>
<p>a) Matrix#[row,col] should behave in a consisten way if either row or col is out of bounds.<br>
Currently it returns nil vs raises an obscure error (See redmine #1518.)</p>
<p>b) Matrix[[1]].row(2) raises an obscure error, while Matrix[[1]].column(2) returns Vector[nil, nil]</p>
<p>c) In a similar vein, Matrix[[1]].minor(2..2,1..1) currently raises an error but not<br>
Matrix[[1]].minor(1..1,2..2)</p>
<p>Solutions:<br>
a) To be consistent with array lookup using [], Matrix#[] should return nil for out of bounds elements.<br>
A #fetch method could be added, but the fact that matrices normally won't contain nil or false<br>
makes it easy to deal with out of bounds references, e.g. m[r, c] || 0</p>
<p>b) Contrary to nil, it is not easy nor useful to deal with Vector[nil, nil, ...].<br>
#row, and #column could raise an IndexError, but it is more useful and<br>
more coherent with Array#at, etc... to return nil.</p>
<p>c) The same way Matrix#row and #col can be related to Array#at,<br>
Matrix#minor should have similar semantics to Array#slice. If either starting point<br>
is out of bounds, nil is returned. Otherwise a Matrix is returned, although it can<br>
be smaller than what was requested. This is similar to<br>
[:a, :b].slice(3..10) # => nil<br>
[:a, :b].slice(2..10) # => []<br>
[:a, :b].slice(1..10) # => [:b]<br>
Matrix[[1], [2]].minor(0..10, 2..10) # => nil<br>
Matrix[[1], [2]].minor(0..10, 1..10) # => Matrix[[], []]<br>
Matrix[[1], [2]].minor(1..10, 0..10) # => Matrix[[2]]</p>
<ol start="6">
<li>Matrix#collect, Vector#collect, #collect2, #map2 should return enumerators if no block is given</li>
</ol>
<p>This would be more useful and is consistent with Array#each, etc...</p>
<ol start="7">
<li>Matrix#hash should have less collisions</li>
</ol>
<p>Currently, the following matrices have the same hash:<br>
Matrix[]<br>
Matrix[[0,0], [0,0]]<br>
Matrix[[1,0], [0,1]]<br>
Matrix[[42,42], [666,666]]<br>
Matrix[[1,2,3,4], [5,6,1,2], [3,4,5,6]]</p>
<p>Ideally, these should have different hashes, since they are different matrices.</p>
<ol start="8">
<li>Matrix#compare_by_row_vectors, Vector#compare_by and Vector#init_elements should be made private or disappear.</li>
</ol>
<p>As per the documentation, these are not meant to be used.<br>
As such it would be best if they didn't appear in the list of methods.</p>
<p>The attached patch addresses all these issues.</p>
<p>Moreover, it addresses all matrix-related issues I could find on redmine:<br>
<a href="http://redmine.ruby-lang.org/issues/show/1020" class="external">http://redmine.ruby-lang.org/issues/show/1020</a><br>
<a href="http://redmine.ruby-lang.org/issues/show/1515" class="external">http://redmine.ruby-lang.org/issues/show/1515</a><br>
<a href="http://redmine.ruby-lang.org/issues/show/1516" class="external">http://redmine.ruby-lang.org/issues/show/1516</a><br>
<a href="http://redmine.ruby-lang.org/issues/show/1517" class="external">http://redmine.ruby-lang.org/issues/show/1517</a><br>
<a href="http://redmine.ruby-lang.org/issues/show/1518" class="external">http://redmine.ruby-lang.org/issues/show/1518</a><br>
<a href="http://redmine.ruby-lang.org/issues/show/1526" class="external">http://redmine.ruby-lang.org/issues/show/1526</a><br>
<a href="http://redmine.ruby-lang.org/issues/show/1531" class="external">http://redmine.ruby-lang.org/issues/show/1531</a></p>
<p>Also fixed a bug with #determinant and #determinant_e that would raise an error for some matrices<br>
(for instance any square matrix with m[0][0] == 0, e.g. Matrix[[0,1],[2,3]].determinant # => error raised)</p>
<p>Finally, the following methods are performing faster:<br>
Matrix#collect<br>
Matrix#transpose<br>
Matrix#==<br>
Matrix#eql?<br>
Matrix#hash<br>
Vector#collect<br>
Vector#map2</p>
<p>Note that the branch 'runpaint' of rubyspecs has specs to this patch.<br>
=end</p> Ruby master - Bug #1531 (Closed): Matrix#determinant fails on some matriceshttps://bugs.ruby-lang.org/issues/15312009-05-29T04:17:19Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
ruby1.9 -r matrix -e 'Matrix[[0,1],[1,0]].determinant'<br>
/usr/local/ruby191/lib/ruby/1.9.1/matrix.rb:685:in <code>block (2 levels) in determinant': undefined method </code>+' for nil:NilClass (NoMethodError)<br>
from /usr/local/ruby191/lib/ruby/1.9.1/matrix.rb:684:in <code>loop' from /usr/local/ruby191/lib/ruby/1.9.1/matrix.rb:684:in </code>block in determinant'<br>
from /usr/local/ruby191/lib/ruby/1.9.1/matrix.rb:681:in <code>loop' from /usr/local/ruby191/lib/ruby/1.9.1/matrix.rb:681:in </code>determinant'<br>
from -e:1:in `'</p>
<p>Same with determinant_e.</p>
<p>To fix: gsub('ii','i') in matrix.rb<br>
=end</p> Ruby master - Bug #1510 (Closed): [patch] String#partition can return wrong result or crashhttps://bugs.ruby-lang.org/issues/15102009-05-25T07:36:38Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
The attached patch fixes a problem that occurs when the argument of String#partition needs to be converted using :to_str.</p>
<p>E.g:</p>
<p>class C<br>
def to_str<br>
"foo"<br>
end<br>
end<br>
p "foo-bar".partition(C.new)</p>
<p>Before patch:<br>
["", #<C:0x2c62a8>, "foo-bar"]</p>
<p>After patch:<br>
["", "foo", "-bar"]</p>
<p>RubySpecs has been updated. Without the version guard, it crashes Ruby.<br>
=end</p> Ruby master - Bug #1487 (Closed): String#each_char must return selfhttps://bugs.ruby-lang.org/issues/14872009-05-19T14:27:48Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
str.each_char{} currently returns a copy of str. It should return self. This also affects Ruby 1.8.7</p>
<p>Poor man's diff for rb_str_each_char:</p>
<pre><code> rb_encoding *enc;
</code></pre>
<ul>
<li>VALUE orig = str;<br>
RETURN_ENUMERATOR(str, 0, 0);<br>
str = rb_str_new4(str);<br>
...</li>
</ul>
<ul>
<li>return str;</li>
</ul>
<ul>
<li>return orig;<br>
=end</li>
</ul> Ruby master - Bug #1448 (Closed): [patch] Proper handling of recursive arrayshttps://bugs.ruby-lang.org/issues/14482009-05-09T11:47:45Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Dealing with recursive arrays & hashes can be tricky.</p>
<p>The current handling of recursive arrays is much improved over that of Ruby 1.8.6. Array comparison still has some bugs though.</p>
<p>For instance:<br>
x = []; x << x<br>
y = [[x]]<br>
x == y # ==> true<br>
y == x # ==> false, should be true!</p>
<p>Morevoer, recursive arrays that are built the same way are not recognized as equal:<br>
z = []; z << z<br>
x == z # ==> false, should be true!</p>
<p>Needless to say, arrays that have the same elements (e.g. a single element, containing a single element, ...) but built differently way are not recognized as equal:<br>
stone = []; stepping = [stone]; stone << stepping<br>
x == stepping # ==> false, would be nice to be true!</p>
<p>The attached patch fixes all of these problems :-)</p>
<ul>
<li>How:<br>
The function rb_exec_recursive handles the recursivity by pushing and poping the elements it encounters for a given method (for example eql?). For such comparisons, instead of keeping track of the elements it encounters, I modified it so that it keeps track of both the elements being compared. A recursion is detected only when a matching pair is found.</li>
</ul>
<p>This takes care of the first problem. For the next two, we only need to observe that if we have a recursion on the pair (x,y) when comparing x and y, then it is because they are not different! Changing the return value for recursive cases from nil (not comparable) / false (different) to Qundef (unknown yet) makes comparison of complex recursive "trees" work beautifully. I've added some cute samples in rubyspecs (core/array/shared/equal.rb)</p>
<ul>
<li>Implementation details:<br>
Previous recursive_push/pop/check maintained a hash of encountered object ids, setting hash[obj] = true. I modified them so that in "paired" cases, it sets hash[obj] = paired_obj. If a pair (obj, different_paired_obj) is encountered later on, I set hash[obj] to {paired_obj => true, different_paired_obj => true}.</li>
</ul>
<p>This way, there is basically no runtime cost to this technique, except in the complex recursive cases. Only for these complex cases is there a small additional cost for the hash creation/destruction.</p>
<ul>
<li>Last problem:<br>
There is one more problem that my patch doesn't cover (lack of mri-fu): hashes for recursive structures are incorrect. As per the official doc, "a.eql? b" should imply "a.hash == b.hash". On the other hand, we have (before or after my patch):<br>
a = [x]<br>
x.eql? a # ==> true<br>
a.eql? x # ==> true<br>
x.hash == a.hash # ==> false, should have same hash</li>
</ul>
<p>The solution is that when calculating the hash for an array, if a recursion is detected, then the hash should return a fixed value (say 0 or -length) <em>for the original</em> array. Currently, 0 is returned but at the level that the recursion is detected. In Ruby pseudo-code, it would look like:</p>
<pre><code> static VALUE
recursive_hash(VALUE ary, VALUE dummy, int recur)
{
long i, h;
VALUE n;
if (recur) {
</code></pre>
<ul>
<li>
<pre><code> raise HashingRecursionDetected
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code> return LONG2FIX(0);
}
h = rb_hash_start(RARRAY_LEN(ary));
for (i=0; i<RARRAY_LEN(ary); i++) {
n = rb_hash(RARRAY_PTR(ary)[i]);
h = rb_hash_uint(h, NUM2LONG(n));
}
h = rb_hash_end(h);
return LONG2FIX(h);
</code></pre>
<p>}</p>
<p>static VALUE<br>
rb_ary_hash(VALUE ary)<br>
{<br>
return rb_exec_recursive(recursive_hash, ary, 0);</p>
</li>
</ul>
<ul>
<li>rescue HashingRecursionDetected</li>
<li>
<pre><code> return -length
</code></pre>
}</li>
</ul>
<p>A similar modification must be made for hash.c.</p>
<p>Thanks</p>
<p>Marc-André Lafortune<br>
=end</p> Ruby master - Bug #1440 (Closed): Array#flatten!(0) should return nil, not selfhttps://bugs.ruby-lang.org/issues/14402009-05-07T15:42:37Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
As per doc, flatten!(0) does not make modifications and should thus return nil.</p>
<p>[].flatten! # ==> nil<br>
[].flatten!(42) # ==> nil<br>
[].flatten!(-1) # ==> nil<br>
[].flatten!(0) # ==> []</p>
<p>Poor man's diff for "rb_ary_flatten_bang"</p>
<ul>
<li>
<pre><code>if (level == 0) return ary;
</code></pre>
</li>
</ul>
<ul>
<li>
<pre><code>if (level == 0) return Qnil;
</code></pre>
</li>
</ul>
<p>=end</p> Ruby master - Bug #1439 (Closed): Array#sample returns wrong results for negative argumenthttps://bugs.ruby-lang.org/issues/14392009-05-07T12:27:25Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
$ ruby1.9 -v -e "p [1,2].sample(-1)"<br>
ruby 1.9.2dev (2009-05-06 trunk 23352) [i386-darwin9.6.0]<br>
[1, 2, false]<br>
=end</p> Ruby master - Bug #1385 (Closed): Wonderful undocumented feature in Ruby 1.8.7 & 1.9https://bugs.ruby-lang.org/issues/13852009-04-17T13:40:20Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
6 months ago, I begged for a natural way to construct a Hash from key-value pairs: <a href="http://redmine.ruby-lang.org/issues/show/666" class="external">http://redmine.ruby-lang.org/issues/show/666</a><br>
Maybe because of a lack of superstitious devil worshippers, there was no additional comment on this issue # 666, which seems even stranger after a discovery I made by pure random luck (hey, my last name is not Lafortune for nothing!). It appears there <em>already is</em> a way, using Hash::[]</p>
<p>Example:<br>
Hash[[[:i_like, :ruby], [:hello, "world!"], [:answer, 42]]]<br>
=> {:i_like => :ruby, :hello => "world!", :answer => 42}</p>
<p>Wouhou, exciting! This works in both Ruby 1.8.7 and 1.9.1, but it is not documented <em>anywhere</em> where it should:<br>
<a href="http://www.ruby-doc.org/core-1.9/classes/Hash.html#M002653" class="external">http://www.ruby-doc.org/core-1.9/classes/Hash.html#M002653</a><br>
<a href="http://www.ruby-doc.org/core-1.8.7/classes/Hash.html#M000148" class="external">http://www.ruby-doc.org/core-1.8.7/classes/Hash.html#M000148</a><br>
<a href="http://svn.ruby-lang.org/repos/ruby/tags/v1_8_7/NEWS" class="external">http://svn.ruby-lang.org/repos/ruby/tags/v1_8_7/NEWS</a><br>
<a href="http://eigenclass.org/hiki/Changes+in+Ruby+1.9" class="external">http://eigenclass.org/hiki/Changes+in+Ruby+1.9</a><br>
The Ruby Programming Language (section 9.5.3.1)</p>
<p>At first I thought maybe my satanic incantations were to thank for this hidden feature, but the huge 1.9 changelog reads:</p>
<p>Fri Oct 26 01:48:28 2007 Yukihiro Matsumoto <a href="mailto:matz@ruby-lang.org" class="email">matz@ruby-lang.org</a></p>
<pre><code>* hash.c (rb_hash_s_create): Hash#[] now takes assocs as source of
hash conversion.
</code></pre>
<p>So, thank you Matz!</p>
<p>I'm thus filing a bug report for the missing documentation, praying that the reason it is not documented is a simple oversight and that we can officially count on this for the future. In any case I eagerly included this cool feature in my backports for 1.8.x (<a href="http://github.com/marcandre/backports" class="external">http://github.com/marcandre/backports</a> ) since I still don't get the point of 1.8.7 (<a href="http://blog.marc-andre.ca/2009/04/whats-point-of-ruby-187.html" class="external">http://blog.marc-andre.ca/2009/04/whats-point-of-ruby-187.html</a> ) and I'll use Hash::[] until we get (one day maybe) my dreamed Enumerable#to_hash which I still favor.</p>
<p>I'd propose an updated doc similar to the following:</p>
<p>/*</p>
<ul>
<li>call-seq:</li>
<li>
<pre><code>Hash[ key, value, ... ] => hash
</code></pre>
</li>
<li>
<pre><code>Hash[ [ [key, value], ... ] ] => hash
</code></pre>
</li>
<li>
<pre><code>Hash[ object ] => hash
</code></pre>
</li>
<li>
<li>Creates a new hash populated with the given objects. Equivalent to</li>
<li>the literal <code>{ <i>key</i> => <i>value</i>, ... }</code>. In the first</li>
<li>form, keys and values occur in pairs, so there must be an even number of arguments.</li>
<li>The second and third form take a single argument which is either</li>
<li>an array of key-value pairs or an object convertible to a hash.</li>
<li>
<li>
<pre><code>Hash["a", 100, "b", 200] #=> {"a"=>100, "b"=>200}
</code></pre>
</li>
<li>
<pre><code>Hash[ [ ["a" => 100], ["b" => 200] ] ] #=> {"a"=>100, "b"=>200}
</code></pre>
</li>
<li>
<pre><code>Hash["a" => 100, "b" => 200] #=> {"a"=>100, "b"=>200}
</code></pre>
</li>
<li>
<pre><code>{"a" => 100, "b" => 200} #=> {"a"=>100, "b"=>200}
</code></pre>
</li>
</ul>
<p>*/</p>
<p>Is it just me or is the last example not quite insightful? In any case, if a different text than mine is used, note that the present version still mentions the old 1.8 syntax: <code>{ <i>key</i>, <i>value</i>, ... }</code></p>
<p>Is there a prize for the most long-winded bug report just for the documentation? To be a sure winner, I'll add that I find interesting that my infamous feature request # 666 would make the second form merge naturally into the third, since an array of key-value pairs would be convertible to a hash!</p>
<p>Thank you for your attention,</p>
<p>Marc-André Lafortune<br>
=end</p> Ruby master - Bug #1165 (Closed): Range.eql? and Range.== bug with subclasseshttps://bugs.ruby-lang.org/issues/11652009-02-17T05:10:45Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
Contrary to the documentation (and to what I would expect):</p>
<p>class TrivialRangeSubclass < Range<br>
end</p>
<p>TrivialRangeSubclass.new(0,1) == Range.new(0,1) # ==> false</p>
<p>This bug is present in the current versions of ruby 1.8.7 and 1.9.1. As a matter of curiosity, I checked both JRuby (1.1.6) and rubinius (0.10.0) and they both return true (as they should).</p>
<p>Although I'm not familiar with the source code, it seams like a simple change, so I've included a patch for the 1.9.1 version. I hope I did things correctly! Changelog could read like:</p>
<p>Mon Feb 16 14:35:35 2009 Marc-Andre Lafortune <a href="mailto:ruby-lang@marc-andre.ca" class="email">ruby-lang@marc-andre.ca</a></p>
<pre><code>* range.c (range_eql, range_eq): fixed equality to work for
subclasses of Range.
* test/ruby/test_range.rb: add assertions for above.
</code></pre>
<p>Thank you!<br>
=end</p> Ruby master - Feature #666 (Rejected): Enumerable::to_hashhttps://bugs.ruby-lang.org/issues/6662008-10-20T14:25:23Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>=begin<br>
There are many ways to obtain an array from enumerables (to_a, map, ...).<br>
There is no natural way to obtain a hash from an enumerable (except for Hash[some_array]).<br>
There is a Hash::to_a but no Array::to_hash.<br>
Here is what I would like:</p>
<p>[[:hello, "world"], [:choice, [:red_pill, :blue_pill]]].to_hash ==> {:hello=>"world", :choice=>[:red_pill, :blue_pill]}<br>
(1..3).to_hash{|n| [n, n**2]} ==> {1 => 1, 2 ==> 4, 3 ==> 9}</p>
<p>I propose to add the following Enumerable::to_hash :</p>
<p>module Enumerable<br>
def to_hash<br>
result = {}<br>
self.each do |key, value|<br>
key, value = yield(key, value) if block_given?<br>
result[key] = value<br>
end<br>
result<br>
end<br>
end</p>
<p>Since Hash::to_a returns an array of key-value pairs, I fell it's natural that a block to construct a Hash should return key-value pairs.<br>
This definition has nice symmetric properties: for any Hash h, the following all return a copy of h.<br>
h.to_a.to_hash<br>
h.to_hash{|p| p}<br>
h.to_hash{|k,v| [k,v]}<br>
h.keys.zip(h.values).to_hash</p>
<p>Thank you for your attention,</p>
<p>Marc-Andre Lafortune<br>
=end</p>