Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112023-01-03T14:00:26ZRuby Issue Tracking System
Redmine Ruby master - Misc #19304 (Open): Kernel vs Object documentationhttps://bugs.ruby-lang.org/issues/193042023-01-03T14:00:26Zzverok (Victor Shepelev)zverok.offline@gmail.com
<p>The restating of the problems raised in <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Move public methods from Kernel to Object (Rejected)" href="https://bugs.ruby-lang.org/issues/19300">#19300</a>, from scratch.</p>
<p>I believe it is rather a topic of <strong>community significance</strong> and would be happy if it is possible to <strong>discuss on dev-meeting</strong>, even if the outcome would probably "let's change RDoc in this or that way".</p>
<p>So, the problem statement:</p>
<ol>
<li>
<code>Kernel</code> module defines two "types" of methods: private ones, that pretend to be global (like <code>puts</code>), but actually available from inside every object; and public ones (like <code>#class</code> or <code>#frozen?</code>) that are present in every object including <code>Kernel</code>.</li>
<li>Since the beginning of times, docs provided an illusion that the second type of the methods belongs to <code>Object</code> class, which is, in fact, devoid of its own definitions, just includes <code>Kernel</code>. This was handled by special RDoc hack (which, basically, forcefully <a href="https://github.com/ruby/rdoc/blob/017bb9fa496ee0e0959facba694a053008d1ecb0/lib/rdoc/parser/c.rb#L477" class="external">reattached definition</a> of public methods if they are defined in <code>Kernel</code>, to <code>Object</code>)</li>
<li>The RDoc hack was working in C code only, so after introduction of <code>kernel.rb</code> the illusion started to crumble: methods like <code>#tap</code>, <code>#then</code>, <code>#class</code> <a href="https://docs.ruby-lang.org/en/3.2/Kernel.html" class="external">are now documented</a> as belonging to <code>Kernel</code> (breaking the tradition of public methods being documented in <code>Object</code>)</li>
<li>This is all inconsistent and confusing, and I believe, adds to friction both for newcomers and curious investigators of the language!</li>
</ol>
<p>Additionally, I believe:</p>
<ol>
<li>That the distinction of "two kinds of methods" is useful (saying from a practical experience with explaining Ruby while mentoring, writing articles, and discussing with colleagues)</li>
<li>But, considering everything, I agree with what <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/772">@Eregon (Benoit Daloze)</a> and <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/4">@nobu (Nobuyoshi Nakada)</a> say in <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Move public methods from Kernel to Object (Rejected)" href="https://bugs.ruby-lang.org/issues/19300">#19300</a>: pretending that methods belong not to the module they really belong to is not the optimal way to document things!</li>
</ol>
<p>So, the options I see (save for "do nothing and let things sort themselves somehow"):</p>
<ol>
<li>Change Ruby's implementation so public methods would really belong to <code>Object</code>. Actually, I don't believe anybody would agree to experiment on this scale, so just listing it here for completeness.</li>
<li>Just remove the RDoc hack; all methods would belong to <code>Kernel</code>, and maybe some introductory free-form text will instruct that they are different. <strong>Pro:</strong> Easy to do. <strong>Contra:</strong> The <code>Kernel</code> docs would be super-confusing.</li>
<li>Continue to maintain the hack in RDoc and extend it to <code>kernel.rb</code> (so methods like <code>#clone</code> and <code>#frozen?</code> would be still in <code>Object</code>). <strong>Pro:</strong> Relatively easy to do, will maintain structure many people used to. <strong>Contra:</strong> This is still a lie, methods belong to <code>Kernel</code>, not <code>Object</code>.</li>
<li>Adjust RDoc to a) be able to separately list <strong>public</strong> and <strong>private</strong> methods in two different lists, and add intro for <code>Kernel</code> explaining how to treat those. <strong>Pro:</strong> Probably the best correspondence to reality? <strong>Contra:</strong> Not sure how easy it is to change RDoc this way; and other renderers (like ruby-doc.com and rubyapi.org) would need to adjust themselves.</li>
</ol>
<p>So far, (4) looks the most reasonable (if (1) is 100% impossible, that is!)</p> Ruby master - Feature #19059 (Open): Introduce top level `module TimeoutError` for aggregating va...https://bugs.ruby-lang.org/issues/190592022-10-15T03:04:07Zioquatix (Samuel Williams)samuel@oriontransfer.net
<p>This proposal was originally part of <a href="https://bugs.ruby-lang.org/issues/18630" class="external">https://bugs.ruby-lang.org/issues/18630</a> but was removed because we could not decide on the name.</p>
<p>Introduce the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">TimeoutError</span>
<span class="k">end</span>
<span class="no">IO</span><span class="o">::</span><span class="no">TimeoutError</span><span class="p">.</span><span class="nf">include</span><span class="p">(</span><span class="no">TimeoutError</span><span class="p">)</span>
<span class="no">Regexp</span><span class="o">::</span><span class="no">TimeoutError</span><span class="p">.</span><span class="nf">include</span><span class="p">(</span><span class="no">TimeoutError</span><span class="p">)</span>
<span class="c1"># Maybe?</span>
<span class="no">Timeout</span><span class="o">::</span><span class="no">Error</span><span class="p">.</span><span class="nf">include</span><span class="p">(</span><span class="no">TimeoutError</span><span class="p">)</span>
</code></pre>
<p>It may be easier for users.</p>
<p>This was discussed before with the following conclusion:</p>
<ul>
<li>Top level <code>TimeoutError</code> is available.</li>
<li>Using a module for a <code>TimeoutError</code> may not be consistent with other top level <code>class #{thing}Error</code>.</li>
</ul> Ruby master - Feature #17849 (Open): Fix Timeout.timeout so that it can be used in threaded Web s...https://bugs.ruby-lang.org/issues/178492021-05-05T01:41:09Zduerst (Martin Dürst)duerst@it.aoyama.ac.jp
<p>Making this a separate issue from <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Add support for Regexp timeouts (Closed)" href="https://bugs.ruby-lang.org/issues/17837">#17837</a></p>
<p>Eregon (Benoit Daloze) wrote in <a href="https://bugs.ruby-lang.org/issues/17837#note-10" class="external">https://bugs.ruby-lang.org/issues/17837#note-10</a> (which is about timeouts for regular expressions):</p>
<blockquote>
<p>I think fixing Timeout.timeout might be possible.<br>
The main/major issue is it can trigger within <code>ensure</code>, right? Is there anything else?<br>
We could automatically mask <code>Thread#raise</code> within <code>ensure</code> so it only happens after the <code>ensure</code> body completes.<br>
And we could still have a larger "hard timeout" if an <code>ensure</code> takes way too long (shouldn't happen, but one cannot be sure).<br>
I recall discussing this with <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/6346">@schneems (Richard Schneeman)</a> some time ago on Twitter.</p>
</blockquote> Ruby master - Feature #17830 (Open): Add Integer#previous and Integer#prev https://bugs.ruby-lang.org/issues/178302021-04-26T17:27:05Zrafasoares (Rafael Soares)rafasoaresms@gmail.com
<p>I think <code>Integer#pred</code> is great as the inverse of <code>#succ</code>, but it reads a bit weird as the inverse of <code>#next</code>, which might be preferable for those going for a more "reads like English" approach.</p>
<p>On that note, <code>#previous</code> reads better, but it's also twice as long as <code>#pred</code> (or even <code>#next</code>). Which is why I've also added the shorthand <code>#prev</code></p>
<p>Since Ruby strives for readability, I always thought it was weird that the team omitted this improvement.</p>
<p>Also, I thought about writing a gem for this, but:</p>
<ol>
<li>Do we really want to add another gem for such a simple change to every project?</li>
<li>Monkey-patching gems feel dirty.</li>
</ol>
<p>Finally, I want to mention that I tried looking for previous discussions on this topic, as it seems likely someone would've brought this up at some point, but was unsuccessful. Probably due to the massive amount of baggage in the core issue tracker and mailing lists, I could've missed something among the noise.</p>
<p>I've created a fork on GitHub (<a href="https://github.com/rafasoares/ruby/commit/05119848b1f480db2e809f964528799030cc7ebb" class="external">https://github.com/rafasoares/ruby/commit/05119848b1f480db2e809f964528799030cc7ebb</a>) in order to open a PR, but decided to open this ticket as well, after reading the contributing guide more carefully.</p> Ruby master - Feature #17785 (Open): Allow named parameters to be keywordshttps://bugs.ruby-lang.org/issues/177852021-04-08T15:08:40Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>We should allow named parameters to be keywords and use add a trailing <code>_</code> to the corresponding variable:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">check</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="k">class</span><span class="p">:)</span>
<span class="n">arg</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="n">class_</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">check</span><span class="p">(</span><span class="mi">42</span><span class="p">,</span> <span class="ss">class: </span><span class="no">Integer</span><span class="p">)</span> <span class="c1"># => true</span>
</code></pre>
<p>Currently, if we want such an API we have to use <code>**rest</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">check</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="o">**</span><span class="n">rest</span><span class="p">)</span>
<span class="n">class_</span> <span class="o">=</span> <span class="n">rest</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="ss">:class</span><span class="p">)</span> <span class="p">{</span> <span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">(</span><span class="s1">'missing keyword: :class'</span><span class="p">)}</span>
<span class="k">if</span> <span class="n">rest</span><span class="p">.</span><span class="nf">size</span> <span class="o">></span> <span class="mi">1</span>
<span class="n">unknown</span> <span class="o">=</span> <span class="n">rest</span><span class="p">.</span><span class="nf">keys</span> <span class="o">-</span> <span class="p">[</span><span class="ss">:class</span><span class="p">]</span>
<span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">(</span><span class="s2">"unknown keyword(s): :</span><span class="si">#{</span><span class="n">unknown</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">', :'</span><span class="p">)</span><span class="si">}</span><span class="s2">)
end
arg.is_a?(class_)
end
</span></code></pre>
<p>This is very verbose, much less convenient, much less readable, prevents <code>steep</code> from generating the proper signature, etc.</p>
<p>We should do the same for pattern match.</p> Ruby master - Feature #17288 (Open): Optimize __send__ call with a literal method namehttps://bugs.ruby-lang.org/issues/172882020-10-27T08:32:40Zmrkn (Kenta Murata)muraken@gmail.com
<p>I made a patch to optimize a <code>__send__</code> call with a literal method name. This optimization replaces a <code>__send__</code> method call with a <code>send</code> instruction. The patch is available in <a href="https://github.com/ruby/ruby/pull/3707" class="external">this pull-request</a>.</p>
<p>By this change, the redefined <code>__send__</code> method is no longer called when it is called by a literal method name. I guess it is no problem because the following warning message is displayed for a long time.</p>
<pre><code>$ ruby -e 'def __send__; end'
-e:1: warning: redefining `__send__' may cause serious problems
</code></pre>
<p>This change makes the optimized case x5~x6 faster. The benchmark result is below:</p>
<pre><code>$ make benchmark COMPARE_RUBY="../../ruby/build-o3/ruby" ITEM=vm_send.yml
(snip)
# Iteration per second (i/s)
| |compare-ruby|built-ruby|
|:------------|-----------:|---------:|
|vm_send | 18.536M| 113.778M|
| | -| 6.14x|
|vm_send_var | 18.085M| 16.595M|
| | 1.09x| -|
</code></pre> Ruby master - Feature #17279 (Open): Allow a negative step in Range#step with a blockhttps://bugs.ruby-lang.org/issues/172792020-10-22T02:23:48Zmrkn (Kenta Murata)muraken@gmail.com
<p><code>Range#step</code> prohibits a negative step when a block is given.</p>
<pre><code>>> (6..3).step(-1) {|i| p i }
Traceback (most recent call last):
5: from /home/mrkn/.rbenv/versions/2.7/bin/irb:23:in `<main>'
4: from /home/mrkn/.rbenv/versions/2.7/bin/irb:23:in `load'
3: from /home/mrkn/.rbenv/versions/2.7.1/lib/ruby/gems/2.7.0/gems/irb-1.2.4/exe/irb:11:in `<top (required)>'
2: from (irb):1
1: from (irb):1:in `step'
ArgumentError (step can't be negative)
</code></pre>
<p>But <code>Range#step</code> allows a negative step when it is called without a block. In this case, <code>Range#step</code> creates an ArithmeticSequence, and <code>ArithmeticSequence#each</code> can iterate with a negative step.</p>
<pre><code>>> (6..3).step(-1).each {|i| p i }
6
5
4
3
=> ((6..3).step(-1))
</code></pre>
<p>I think the prohibition of a negative step in <code>Range#step</code> has already been meaningless, so it may be better to permit it for consistency.</p> Ruby master - Feature #17184 (Open): No stdlib function to perform simple string replacementhttps://bugs.ruby-lang.org/issues/171842020-09-24T11:37:04Zsheerun (Adam Stankiewicz)sheerun@sher.pl
<p>I have following simple <code>build.rb</code>:</p>
<pre><code class="rb syntaxhl" data-language="rb"><span class="n">template</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s1">'template.vim'</span><span class="p">)</span>
<span class="n">script</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s1">'script.vim'</span><span class="p">)</span>
<span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="s1">'app.vim'</span><span class="p">,</span> <span class="n">template</span><span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="s2">"SCRIPT"</span><span class="p">,</span> <span class="n">script</span><span class="p">))</span>
</code></pre>
<p>And then following <code>template.vim</code>:</p>
<pre><code class="vim syntaxhl" data-language="vim"><span class="c">" some header</span>
SCRIPT
</code></pre>
<p>Plus following <code>script.vim</code>:</p>
<pre><code class="vim syntaxhl" data-language="vim"><span class="k">if</span> <span class="nv">g:something</span> <span class="p">=~</span> <span class="s2">"\s\+"</span>
echo <span class="s1">'g:something is empty'</span>
<span class="k">endif</span>
</code></pre>
<p>I'd expect that the script above produces <code>app.vim</code> with following contents:</p>
<pre><code class="vim syntaxhl" data-language="vim"><span class="c">" some header</span>
<span class="k">if</span> <span class="nv">g:something</span> <span class="p">=~</span> <span class="s2">"\s\+"</span>
echo <span class="s1">'g:something is empty'</span>
<span class="k">endif</span>
</code></pre>
<p>Unfortunately it produces following:</p>
<pre><code class="vim syntaxhl" data-language="vim"><span class="c">" some header</span>
<span class="k">if</span> <span class="nv">g:something</span> <span class="p">=~</span> <span class="s2">"\s"</span>
echo <span class="s1">'g:something is empty'</span>
<span class="k">endif</span>
</code></pre>
<p>It's probably because gsub interprets <code>\+</code> in script as back-reference.</p>
<p>I tried to find replacement function in ruby that just replaces one string with something else, without interpreting replacement in any way, but surprisingly I haven't found any.. Am I mistaken?</p> Ruby master - Feature #16992 (Open): Sets: officially orderedhttps://bugs.ruby-lang.org/issues/169922020-06-26T20:30:50Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Officially, set elements have uncertain order. This predades when Hash started being ordered (Ruby 1.9.0, Xmas 2007). Sets have since been de-facto insertion-ordered. FYI, in those 13 years, there have been about 70 commits to <code>lib/set.rb</code>.</p>
<p>I have the impression that a non-negligible amount of code in the wild rely on sets being ordered, at least under most circumstances. I feel that this should be officialized.</p>
<p>If sets are truly unordered, then why do we hesitate to make an optimization of <code>&</code> and <code>|</code>: <a href="https://bugs.ruby-lang.org/issues/15281" class="external">https://bugs.ruby-lang.org/issues/15281</a></p>
<p>See also: <a href="https://bugs.ruby-lang.org/issues/14069" class="external">https://bugs.ruby-lang.org/issues/14069</a></p> Ruby master - Feature #16986 (Open): Anonymous Struct literalhttps://bugs.ruby-lang.org/issues/169862020-06-26T06:58:53Zko1 (Koichi Sasada)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>How about introducing anonymous Struct literal such as <code>${a: 1, b: 2}</code>?<br>
It is almost the same as <code>Struct.new(:a, :b).new(1, 2)</code>.</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<a name="Background"></a>
<h2 >Background<a href="#Background" class="wiki-anchor">¶</a></h2>
<p>In many cases, people use hash objects to represent a set of values such as <code>person = {name: "ko1", country: 'Japan'}</code> and access its values through <code>person[:name]</code> and so on. It is not easy to write (three characters <code>[:]</code>!), and it easily introduces misspelling (<code>person[:nama]</code> doesn't raise an error).</p>
<p>If we make a <code>Struct</code> object by doing <code>Person = Struct.new(:name, :age)</code> and <code>person = Person.new('ko1', 'Japan')</code>, we can access its values through <code>person.name</code> naturally. However, it costs coding. And in some cases, we don't want to name the class (such as <code>Person</code>).</p>
<p>Using <code>OpenStruct</code> (<code>person = OpenStruct.new(name: "ko1", country: "Japan")</code>), we can access it through <code>person.name</code>, but we can extend the fields unintentionally, and the performance is not good.</p>
<p>Of course, we can define a class <code>Person</code> with attr_readers. But it takes several lines.</p>
<p>To summarize the needs:</p>
<ul>
<li>Easy to write
<ul>
<li>Doesn't require declaring the class</li>
<li>Accessible through <code>person.name</code> format</li>
</ul>
</li>
<li>Limited fields</li>
<li>Better performance</li>
</ul>
<a name="Idea"></a>
<h2 >Idea<a href="#Idea" class="wiki-anchor">¶</a></h2>
<p>Introduce new literal syntax for an anonymous Struct such as: <code>${ a: 1, b: 2 }</code>.<br>
Similar to Hash syntax (with labels), but with <code>$</code> prefix to distinguish.</p>
<p>Anonymous structs which have the same member in the same order share their class.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="n">s1</span> <span class="o">=</span> <span class="err">$</span><span class="p">{</span><span class="ss">a: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">2</span><span class="p">,</span> <span class="ss">c: </span><span class="mi">3</span><span class="p">}</span>
<span class="n">s2</span> <span class="o">=</span> <span class="err">$</span><span class="p">{</span><span class="ss">a: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">2</span><span class="p">,</span> <span class="ss">c: </span><span class="mi">3</span><span class="p">}</span>
<span class="n">assert</span> <span class="n">s1</span> <span class="o">==</span> <span class="n">s2</span>
<span class="n">s3</span> <span class="o">=</span> <span class="err">$</span><span class="p">{</span><span class="ss">a: </span><span class="mi">1</span><span class="p">,</span> <span class="ss">c: </span><span class="mi">3</span><span class="p">,</span> <span class="ss">b: </span><span class="mi">2</span><span class="p">}</span>
<span class="n">s4</span> <span class="o">=</span> <span class="err">$</span><span class="p">{</span><span class="ss">d: </span><span class="mi">4</span><span class="p">}</span>
<span class="n">assert_equal</span> <span class="kp">false</span><span class="p">,</span> <span class="n">s1</span> <span class="o">==</span> <span class="n">s3</span>
<span class="n">assert_equal</span> <span class="kp">false</span><span class="p">,</span> <span class="n">s1</span> <span class="o">==</span> <span class="n">s4</span>
</code></pre>
<a name="Note"></a>
<h2 >Note<a href="#Note" class="wiki-anchor">¶</a></h2>
<p>Unlike Hash literal syntax, this proposal only allows <code>label: expr</code> notation. No <code>${**h}</code> syntax.<br>
This is because if we allow to splat a Hash, it can be a vulnerability by splatting outer-input Hash.</p>
<p>Thanks to this spec, we can specify anonymous Struct classes at compile time.<br>
We don't need to find or create Struct classes at runtime.</p>
<a name="Implementatation"></a>
<h2 >Implementatation<a href="#Implementatation" class="wiki-anchor">¶</a></h2>
<p><a href="https://github.com/ruby/ruby/pull/3259" class="external">https://github.com/ruby/ruby/pull/3259</a></p>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<a name="Notation"></a>
<h2 >Notation<a href="#Notation" class="wiki-anchor">¶</a></h2>
<p>Matz said he thought about <code>{|a: 1, b: 2 |}</code> syntax.</p>
<a name="Performance"></a>
<h2 >Performance<a href="#Performance" class="wiki-anchor">¶</a></h2>
<p>Surprisingly, Hash is fast and Struct is slow.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Benchmark</span><span class="p">.</span><span class="nf">driver</span> <span class="k">do</span> <span class="o">|</span><span class="n">r</span><span class="o">|</span>
<span class="n">r</span><span class="p">.</span><span class="nf">prelude</span> <span class="o"><<~</span><span class="no">PRELUDE</span><span class="sh">
st = Struct.new(:a, :b).new(1, 2)
hs = {a: 1, b: 2}
class C
attr_reader :a, :b
def initialize() = (@a = 1; @b = 2)
end
ob = C.new
</span><span class="no"> PRELUDE</span>
<span class="n">r</span><span class="p">.</span><span class="nf">report</span> <span class="s2">"ob.a"</span>
<span class="n">r</span><span class="p">.</span><span class="nf">report</span> <span class="s2">"hs[:a]"</span>
<span class="n">r</span><span class="p">.</span><span class="nf">report</span> <span class="s2">"st.a"</span>
<span class="k">end</span>
<span class="cp">__END__
Warming up --------------------------------------
ob.a 38.100M i/s - 38.142M times in 1.001101s (26.25ns/i, 76clocks/i)
hs[:a] 37.845M i/s - 38.037M times in 1.005051s (26.42ns/i, 76clocks/i)
st.a 33.348M i/s - 33.612M times in 1.007904s (29.99ns/i, 87clocks/i)
Calculating -------------------------------------
ob.a 87.917M i/s - 114.300M times in 1.300085s (11.37ns/i, 33clocks/i)
hs[:a] 85.504M i/s - 113.536M times in 1.327850s (11.70ns/i, 33clocks/i)
st.a 61.337M i/s - 100.045M times in 1.631064s (16.30ns/i, 47clocks/i)
Comparison:
ob.a: 87917391.4 i/s
hs[:a]: 85503703.6 i/s - 1.03x slower
st.a: 61337463.3 i/s - 1.43x slower
</span></code></pre>
<p>I believe we can speed up <code>Struct</code> similarly to ivar accesses, so we can improve the performance.</p>
<p>BTW, OpenStruct (os.a) is slow.</p>
<pre><code>Comparison:
hs[:a]: 92835317.7 i/s
ob.a: 85865849.5 i/s - 1.08x slower
st.a: 53480417.5 i/s - 1.74x slower
os.a: 12541267.7 i/s - 7.40x slower
</code></pre>
<p>For memory consumption, <code>Struct</code> is more lightweight because we don't need to keep the key names.</p>
<a name="Naming"></a>
<h2 >Naming<a href="#Naming" class="wiki-anchor">¶</a></h2>
<p>If we name an anonymous class, literals with the same members share the name.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">s1</span> <span class="o">=</span> <span class="err">$</span><span class="p">{</span><span class="n">a</span><span class="p">:</span><span class="mi">1</span><span class="p">}</span>
<span class="n">s2</span> <span class="o">=</span> <span class="err">$</span><span class="p">{</span><span class="n">a</span><span class="p">:</span><span class="mi">2</span><span class="p">}</span>
<span class="nb">p</span> <span class="p">[</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">]</span> <span class="c1">#=> [#<struct a=1>, #<struct a=2>]</span>
<span class="no">A</span> <span class="o">=</span> <span class="n">s1</span><span class="p">.</span><span class="nf">class</span>
<span class="nb">p</span> <span class="p">[</span><span class="n">s1</span><span class="p">,</span> <span class="n">s2</span><span class="p">]</span> <span class="c1">#=> [#<struct A a=1>, #<struct A a=2>]</span>
</code></pre>
<p>Maybe that is not a good behavior.</p> Ruby master - Feature #16894 (Open): Integer division for Ruby 3https://bugs.ruby-lang.org/issues/168942020-05-15T03:20:39Zankane (Andrew Kane)
<p>Hi Ruby team,</p>
<p>It'd be great if division in Ruby matched what we all learned in school.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="mi">1</span> <span class="o">/</span> <span class="mi">2</span> <span class="o">==</span> <span class="mf">0.5</span>
</code></pre>
<p>New developers wouldn't immediately be confused when they try to do division and experienced developers could stop adding to_f to their code (typically after they get tripped up on the first run). In my experience, floating point division is way more common than floor division. This could definitely break existing code, so I understand it's a decision that shouldn't be made lightly. Overall, Ruby is really intuitive, but this is one place where it's not.</p>
<p>It looks like this was considered for Ruby 2.0 as well as few years ago in <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Integer#/ の改訂 (Rejected)" href="https://bugs.ruby-lang.org/issues/5512">#5512</a>, so feel free to close if it's not something you'd like to reconsider right now.</p> Ruby master - Feature #15991 (Open): Allow questionmarks in variable nameshttps://bugs.ruby-lang.org/issues/159912019-07-08T09:18:43Zaquaj (Jérémie Bonal)
<p>Hi,</p>
<p>I thought such an issue would've already been discussed but no number of searches allowed me to find a similar request. Feel free to close if I missed a previous refusal.</p>
<p>From time to time, especially when trying to clear up complex conditional logic, I find myself wishing I could add <code>?</code> to variable names, since I got used to it while naming methods.</p>
<p>For example, currently:</p>
<pre><code>if (node? && terminal?) || (halting && (value == halting))
# ...
end
</code></pre>
<p>becomes</p>
<pre><code>last_node = self.node? && self.terminal?
halt_on_node = halting && (value == halting)
if last_node || halt_on_node
# ...
end
</code></pre>
<p><code>halt_on_node</code> is clear enough, but <code>last_node</code> feels like it would contain a node, instead of expressing its actual purpose ("is the node the last one?").<br>
Right now a developer would have two options as I see them:<br>
1 - extract the conditional to a method <code>def last_node?</code> which can be a bit much if it's the only place this code is called.<br>
2 - rename the variable something like <code>is_last_node</code>, which feels a bit silly since we're in ruby and used to seeing <code>?</code>s for predicates.</p>
<p>Trying to assign to a questionmarked variable (<code>a? = true</code>) raises a <code>SyntaxError</code>. IMHO, it would make for more coherent design to allow it, just like we do in method names.</p>
<p>I was afraid that <code>variable?</code> would be already parsed as beginning a ternary expression (<code>variable?1:3</code>) but this isn't parsed either, the only thing it's used for is for method calls (<code>a?5 <==> a?(5)</code>), so this change wouldn't disrupt any current behavior, the expression would just be looked up like any other call instead of only looking up methods.</p>
<p>The only thing I can see with this is that it might raise the issue of allowing <code>!</code>s in variable names too, which I'm not sure makes a lot of sense (unlike <code>?</code> which denotes "booleanness", a trait shared by variables and methods alike, I can't see how a variable would be "dangerous").</p> Ruby master - Feature #15837 (Open): Module#name_componentshttps://bugs.ruby-lang.org/issues/158372019-05-08T03:49:38Zmrkn (Kenta Murata)muraken@gmail.com
<p>I sometimes wrote the expression like below to extract the components of class path:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">klass</span><span class="p">.</span><span class="nf">name</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s1">'::'</span><span class="p">).</span><span class="nf">last</span>
</code></pre>
<p>Similar expressions can be found in ruby-trunk:</p>
<pre><code>mrkn@mrkn-devel:~/src/github.com/ruby/ruby$ git grep split..::
ext/json/lib/json/common.rb: path.to_s.split(/::/).inject(Object) do |p, c|
ext/openssl/lib/openssl/config.rb: refsec, ref = ref.split('::', 2)
ext/psych/lib/psych/visitors/yaml_tree.rb: method = "visit_#{(klass.name || '').split('::').join('_')}"
lib/bundler/cli/gem.rb: constant_array = constant_name.split("::")
lib/bundler/vendor/molinillo/lib/molinillo/errors.rb: solver_name = opts.delete(:solver_name) { self.class.name.split('::').first }
lib/bundler/vendor/thor/lib/thor/parser/argument.rb: class_name = self.class.name.split("::").last
lib/bundler/vendor/thor/lib/thor/parser/arguments.rb: class_name = self.class.name.split("::").last.downcase
lib/optparse/version.rb: pkg = pkg.split(/::|\//).inject(::Object) {|m, c| m.const_get(c)}
lib/optparse/version.rb: path.split(/::|\//).inject(base) do |klass, name|
lib/rdoc/any_method.rb: name = @full_name.split('::')
lib/rdoc/context.rb: names = ename.split('::')
lib/rdoc/context.rb: path = [prefix] + path.split('::')
lib/rdoc/method_attr.rb: $1.split('::').last. # ClassName => class_name
lib/rdoc/parser/c.rb: ([\w\. \t]+ = \s+)?rb_define_(class|module)_under[\t\w, (]*?"(#{class_name.split('::').last})"%xm then
lib/rdoc/parser/ruby.rb: obj = name_t[:text].split("::").inject(Object) do |state, item|
lib/rdoc/store.rb: name = klass_name.split('::').last
lib/rdoc/store.rb: File.join @path, *klass_name.split('::')
lib/rdoc/store.rb: method_name = method_name.split('::').last
lib/rss/atom.rb: "#{self.class.name.split(/::/).last.downcase}="
lib/rss/atom.rb: target.__send__(self.class.name.split(/::/).last.downcase) {|x| x}
lib/rss/atom.rb: target.__send__("new_#{self.class.name.split(/::/).last.downcase}")
lib/rss/rss.rb: tag_name = klass.name.split(/::/).last
spec/bundler/support/artifice/fail.rb: const = name.split("::").reduce(Object) {|mod, sym| mod.const_get(sym) }
spec/mspec/lib/mspec/utils/name_map.rb: c.split('::').inject(base) do |dir, name|
spec/mspec/lib/mspec/utils/name_map.rb: name = mapping[c.split('::').last] || mapping.fetch(:default)
</code></pre>
<p>I think we need <code>Module#name_components</code> method that returns the array of symbols (or string, I prefer symbols) which comes from splitting name by <code>::</code>.</p> Ruby master - Bug #15764 (Open): Whitespace and control characters should not be permitted in tokenshttps://bugs.ruby-lang.org/issues/157642019-04-11T20:59:47ZBatmanAoD (Kyle Strand)kyle.j.strand@gmail.com
<p>As of Ruby 2.5.1p57, it appears that all valid Unicode code-points above 128 are permitted in tokens. This includes whitespace and control characters.</p>
<p>This was demonstrated here: <a href="https://gist.github.com/qrohlf/7045823" class="external">https://gist.github.com/qrohlf/7045823</a></p>
<p>I have attached the raw download from the above gist.</p>
<p>The issue has been discussed on StackOverflow: <a href="https://stackoverflow.com/q/34455427/1858225" class="external">https://stackoverflow.com/q/34455427/1858225</a></p>
<p>I would say this is arguably a bug, but I am marking this ticket as a "feature" since the current behavior could be considered by-design.</p> Ruby master - Feature #15554 (Open): warn/error passing a block to a method which never use a blockhttps://bugs.ruby-lang.org/issues/155542019-01-22T04:48:10Zko1 (Koichi Sasada)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>Warn or raise an ArgumentError if block is passed to a method which does not use a block.<br>
In other words, detect "block user methods" implicitly and only "block user methods" can accept a block.</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Sometimes, we pass a block to a method which ignores the passed block accidentally.</p>
<pre><code>def my_open(name)
open(name)
end
# user hopes it works as Kernel#open which invokes a block with opened file.
my_open(name){|f| important_work_with f }
# but simply ignored...
</code></pre>
<p>To solve this issue, this feature request propose showing warnings or raising an exception on such case.</p>
<p>Last developer's meeting, matz proposed <code>&nil</code> which declares this method never receive a block. It is explicit, but it is tough to add this <code>&nil</code> parameter declaration to all of methods (do you want to add it to <code>def []=(i, e, &nil)</code>?).<br>
(I agree <code>&nil</code> is valuable on some situations)</p>
<a name="Spec"></a>
<h1 >Spec<a href="#Spec" class="wiki-anchor">¶</a></h1>
<a name="Define-use-a-block-methods"></a>
<h2 >Define "use a block" methods<a href="#Define-use-a-block-methods" class="wiki-anchor">¶</a></h2>
<p>We need to define which method accepts a block and which method does not.</p>
<ul>
<li>(1) method has a block parameter (<code>&b</code>)</li>
<li>(2) method body has `yield'</li>
<li>(3) method body has <code>super</code> (ZSUPER in internal terminology) or <code>super(...)</code>
</li>
<li>(4) method body has singleton method (optional)</li>
</ul>
<p>(1) and (2) is very clear. I need to explain about (3) and (4).</p>
<p>(3). <code>super</code> (ZSUPER) passes all parameters as arguments. So there is no surprise that which can accept <code>block</code>.<br>
However <code>super(...)</code> also passes a block if no explicit block passing (like <code>super(){}</code> or <code>super(&b)</code>) are written.<br>
I'm not sure we need to continue this strange specification, but to keep compatibility depending this spec, I add this rule.</p>
<p>(4). surprisingly, the following code invoke a block:</p>
<pre><code>def foo
class << Object.new
yield
end
end
foo{ p :ok } #=> :ok
</code></pre>
<p>I'm also not sure we need to keep this spec, but to allow this spec, I added (4) rule.<br>
Strictly speaking, it is not required, but we don't keep the link from singleton class ISeq to lexical parent iseq now, so I added it.</p>
<a name="Exceptional-cases"></a>
<h2 >Exceptional cases<a href="#Exceptional-cases" class="wiki-anchor">¶</a></h2>
<p>A method called by <code>super</code> doesn<code>t warn warning even if this method doesn't use a block. The rule (3) can pass blocks easily and there are many methods don</code>t use a block.</p>
<p>So my patch ignores callings by <code>super</code>.</p>
<a name="corner-cases"></a>
<h2 >corner cases<a href="#corner-cases" class="wiki-anchor">¶</a></h2>
<p>There are several cases to use block without (1)-(4) rules.</p>
<h3>
<code>Proc.new/proc/lambda</code> without a block</h3>
<p>Now it was deprecated in r66772 (<a class="changeset" title="proc.c: proc without block * proc.c (proc_new): promoted lambda/proc/Proc.new with no block in..." href="https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/9f1fb0a17febc59356d58cef5e98db61a3c03550">9f1fb0a17febc59356d58cef5e98db61a3c03550</a>).<br>
Related discussion: [Bug <a class="issue tracker-1 status-6 priority-4 priority-default closed" title="Bug: Proc.new with no block shouldn't always warn (Rejected)" href="https://bugs.ruby-lang.org/issues/15539">#15539</a>]</p>
<a name="block_given"></a>
<h3 ><code>block_given?</code><a href="#block_given" class="wiki-anchor">¶</a></h3>
<p><code>block_given?</code> expects block, but I believe we use it with <code>yield</code> or a block parameter.<br>
If you know the usecase without them, please tell us.</p>
<h3>
<code>yield</code> in <code>eval</code>
</h3>
<p>We can't know <code>yield</code> (or (3), (4) rule) in an <code>eval</code> evaluating string at calling time.</p>
<pre><code>def foo
eval('yield`)
end
foo{} # at calling time,
# we can't know the method foo can accept a block or not.
</code></pre>
<p>So I added a warning to use <code>yield</code> in <code>eval</code> like that: <code>test.rb:4: warning: use yield in eval will not be supported in Ruby 3.</code></p>
<p>Workaround is use a block parameter explicitly.</p>
<pre><code>def foo &b
eval('b.call')
end
foo{ p :ok }
</code></pre>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p>Strategy is:</p>
<ul>
<li>[compile time] introduce <code>iseq::has_yield</code> field and check it if the iseq (or child iseq) contains <code>yield</code> (or something)</li>
<li>[calling time] if block is given, check <code>iseq::has_yield</code> flag and show warning (or raise an exception)</li>
</ul>
<p><a href="https://gist.github.com/ko1/c9148ad0224bf5befa3cc76ed2220c0b" class="external">https://gist.github.com/ko1/c9148ad0224bf5befa3cc76ed2220c0b</a></p>
<p>On this patch, now it raises an error to make it easy to detect.<br>
It is easy to switch to show the warning.</p>
<a name="Evaluation-and-discussion"></a>
<h1 >Evaluation and discussion<a href="#Evaluation-and-discussion" class="wiki-anchor">¶</a></h1>
<p>I tried to avoid ruby's tests.</p>
<p><a href="https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786" class="external">https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786</a></p>
<p>Here is a patch.</p>
<p>There are several patterns to avoid warnings.</p>
<a name="tests-for-block_given-Procnew-and-similar-without-block"></a>
<h2 >tests for <code>block_given?</code>, <code>Proc.new</code> (and similar) without block<a href="#tests-for-block_given-Procnew-and-similar-without-block" class="wiki-anchor">¶</a></h2>
<p>Add a dummy block parameter.<br>
It is test-specific issue.</p>
<h2>empty <code>each</code>
</h2>
<p>Some tests add <code>each</code> methods do not <code>yield</code>, like: <code>def each; end</code>.<br>
Maybe test-specific issue, and adding a dummy block parameter.</p>
<a name="Subtyping-duck-typing"></a>
<h2 >Subtyping / duck typing<a href="#Subtyping-duck-typing" class="wiki-anchor">¶</a></h2>
<p><a href="https://github.com/ruby/ruby/blob/c01a5ee85e2d6a7128cccafb143bfa694284ca87/lib/optparse.rb#L698" class="external">https://github.com/ruby/ruby/blob/c01a5ee85e2d6a7128cccafb143bfa694284ca87/lib/optparse.rb#L698</a></p>
<p>This <code>parse</code> method doesn't use <code>yield</code>, but other sub-type's <code>parse</code> methods use.</p>
<h2>
<code>super</code> with <code>new</code> method</h2>
<p><a href="https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-patch-L61" class="external">https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-patch-L61</a></p>
<p>This method override <code>Class#new</code> method and introduce a hook with block (yield a block in this hook code).</p>
<p><a href="https://github.com/ruby/ruby/blob/trunk/lib/rubygems/package/tar_writer.rb#L81" class="external">https://github.com/ruby/ruby/blob/trunk/lib/rubygems/package/tar_writer.rb#L81</a></p>
<p>In this method, call <code>super</code> and it also passing a block. However, called <code>initialize</code> doesn't use a block.</p>
<a name="Change-robustness"></a>
<h2 >Change robustness<a href="#Change-robustness" class="wiki-anchor">¶</a></h2>
<p>This change reduce robustness for API change.</p>
<p><code>Delegator</code> requires to support <code>__getobj__</code> for client classes.<br>
Now <code>__getobj__</code> should accept block but most of <code>__getobj__</code> clients do not call given block.</p>
<p><a href="https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L80" class="external">https://github.com/ruby/ruby/blob/trunk/lib/delegate.rb#L80</a></p>
<p>This is because of delegator.rb's API change.</p>
<p><a href="https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-patch-L86" class="external">https://gist.github.com/ko1/37483e7940cdc4390bf8eb0001883786#file-tests-patch-L86</a></p>
<p>Nobu says calling block is not required (ignoring a block is no problem) so it is not a bug for delegator client classes.</p>
<a name="Found-issues"></a>
<h2 >Found issues.<a href="#Found-issues" class="wiki-anchor">¶</a></h2>
<pre><code>[ 2945/20449] Rinda::TestRingServer#test_do_reply = 0.00 s
1) Error:
Rinda::TestRingServer#test_do_reply:
ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used.
/home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:635:in `test_do_reply'
[ 2946/20449] Rinda::TestRingServer#test_do_reply_local = 0.00 s
2) Error:
Rinda::TestRingServer#test_do_reply_local:
ArgumentError: passing block to the method "with_timeout" (defined at /home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:787) is never used.
/home/ko1/src/ruby/trunk/test/rinda/test_rinda.rb:657:in `test_do_reply_local'
[10024/20449] TestGemRequestSetGemDependencyAPI#test_platform_mswin = 0.01 s
3) Error:
TestGemRequestSetGemDependencyAPI#test_platform_mswin:
ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used.
/home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:655:in `test_platform_mswin'
[10025/20449] TestGemRequestSetGemDependencyAPI#test_platforms = 0.01 s
4) Error:
TestGemRequestSetGemDependencyAPI#test_platforms:
ArgumentError: passing block to the method "util_set_arch" (defined at /home/ko1/src/ruby/trunk/lib/rubygems/test_case.rb:1053) is never used.
/home/ko1/src/ruby/trunk/test/rubygems/test_gem_request_set_gem_dependency_api.rb:711:in `test_platforms'
</code></pre>
<p>These 4 detection show the problem. <code>with_timeout</code> method (used in Rinda test) and <code>util_set_arch</code> method (used in Rubygems test) simply ignore the given block.<br>
So these tests are simply ignored.</p>
<p>I reported them. (<a href="https://github.com/rubygems/rubygems/issues/2601" class="external">https://github.com/rubygems/rubygems/issues/2601</a>)</p>
<a name="raise-an-error-or-show-a-warning"></a>
<h2 >raise an error or show a warning?<a href="#raise-an-error-or-show-a-warning" class="wiki-anchor">¶</a></h2>
<p>At least, Ruby 2.7 should show warning for this kind of violation with <code>-w</code>.<br>
How about for Ruby3?</p> Ruby master - Feature #15445 (Open): Reject '.123' in Float() methodhttps://bugs.ruby-lang.org/issues/154452018-12-21T00:16:38Zmrkn (Kenta Murata)muraken@gmail.com
<p>Since ruby 1.8, Ruby occurs a syntax error for "." floating literal.<br>
But Float() method accepts such form now.</p>
<p>I propose to reject "." form even in Float() method.</p> Ruby master - Feature #15330 (Open): autoload_relativehttps://bugs.ruby-lang.org/issues/153302018-11-21T23:43:41Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>I'd like to propose a way to autoload a constant using a relative path.</p>
<p>It could look like:</p>
<pre><code>autoload_relative :MyConst, 'models/my_const'
</code></pre>
<p>My proposal raises two questions:</p>
<ol>
<li>what's the future of <code>autoload</code>?</li>
</ol>
<p>I believe that <code>autoload</code> has been there for years, it is used successfully and has no real alternative.</p>
<p>I looked at a sample of 430 top gems (took the 500 top ranked according to Libraries.io, removed those that I failed to process). The number of those gems that appear to use <code>autoload</code> at least once is 94 of those (22%).</p>
<p>The number of lines in the code where <code>autoload</code> is called can be quite big. The top 5 are:<br>
vagrant: 235<br>
yard: 206<br>
ffaker: 155<br>
aws-sdk: 152<br>
rdoc: 92</p>
<p>This is a minimum bound, as some gems might be using loops, my processing would only detect the one place in the code with <code>autoload</code>.</p>
<ol start="2">
<li>are many autoladed paths relative?</li>
</ol>
<p>My preliminary numbers indicate that of the 94 gems using autoload, at least 75 are autoloading some relative files. That's a lower bound, as my algorithm is pretty crude and will only count the simplest cases as being relative. An example of gem my algorithm does not detect is <code>yard</code>, because the author wrote a small method to map the relative paths to global paths (code here: <a href="https://github.com/lsegal/yard/blob/master/lib/yard/autoload.rb#L3" class="external">https://github.com/lsegal/yard/blob/master/lib/yard/autoload.rb#L3</a> )</p>
<p>Of those where my processing detects the relative requires, a vast majority are relative. The average is that 94% of autoloaded files are relative and would benefit from <code>require_relative</code></p>
<p>In summary: I am convinced that <code>autoload</code> should remain in Ruby indefinitely. <code>autoload_relative</code> would actually be more useful than <code>autoload</code>. Even if the future of <code>autoload</code> remains uncertain, I would recommend adding <code>autoload_relative</code>; if it is ever decided to actually remove <code>autoload</code>, removing <code>autoload_relative</code> would not really add to the (huge) burden of gem maintainers.</p> Ruby master - Feature #15277 (Open): at_exechttps://bugs.ruby-lang.org/issues/152772018-11-02T19:23:47Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>There's currently no easy way to have code executed before a subsequent call to <code>exec</code>. One has to monkey-patch the builtin method.</p>
<p>I'd like to propose a new method <code>at_exec</code> that would be very similar to <code>at_exit</code>, except that the callbacks are triggered before the current process is replaced by the external command.</p>
<pre><code># This would output "Hello", "Bye", and "Foo"
at_exec { puts "Bye!" }
puts "Hello"
exec "echo Foo"
</code></pre>
<p>Use case: we roll our own in <code>DeepCover</code>. Some test suites will call <code>exec</code>, and we need to store our counters before that happens.</p> Ruby master - Feature #15192 (Open): Introduce a new "shortcut assigning" syntax to convenient se...https://bugs.ruby-lang.org/issues/151922018-10-02T04:54:28Zjjyr (Jinyang Jiang)jjyruby@gmail.com
<p>Motivation:</p>
<p>Introduce a new syntax for convenient setup instance variables for objects.</p>
<p>The problem:</p>
<p>Currently, setup instance variables in Ruby is too verbose.<br>
Basically, we need to write the meaningless assigning code again and again to assign variables</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Person</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="nb">name</span><span class="p">:,</span> <span class="n">age</span><span class="p">:,</span> <span class="n">gender</span><span class="p">:,</span> <span class="n">country</span><span class="p">:)</span>
<span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
<span class="vi">@age</span> <span class="o">=</span> <span class="n">age</span>
<span class="vi">@gender</span> <span class="o">=</span> <span class="n">gender</span>
<span class="vi">@country</span> <span class="o">=</span> <span class="n">country</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># we can use Struct to avoiding this</span>
<span class="no">Person</span> <span class="o">=</span> <span class="no">Struct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">:name</span><span class="p">,</span> <span class="ss">:age</span><span class="p">,</span> <span class="ss">:gender</span><span class="p">,</span> <span class="ss">:country</span><span class="p">,</span> <span class="ss">keyword_init: </span><span class="kp">true</span><span class="p">)</span>
<span class="c1"># let's see a real-world case, which can't use Struct to describe an initializing process, from https://github.com/ciri-ethereum/ciri/blob/748985ccf7a620a2e480706a5a6b38f56409d487/lib/ciri/devp2p/server.rb#L54</span>
<span class="c1"># Because we want to do something more than just assigning instance variables</span>
<span class="k">class</span> <span class="nc">Server</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">private_key</span><span class="p">:,</span> <span class="n">protocol_manage</span><span class="p">:,</span> <span class="ss">bootstrap_nodes: </span><span class="p">[],</span>
<span class="ss">node_name: </span><span class="s1">'Ciri'</span><span class="p">,</span> <span class="ss">tcp_host: </span><span class="s1">'127.0.0.1'</span><span class="p">,</span> <span class="ss">tcp_port: </span><span class="mi">33033</span><span class="p">)</span>
<span class="vi">@private_key</span> <span class="o">=</span> <span class="n">private_key</span>
<span class="vi">@node_name</span> <span class="o">=</span> <span class="n">node_name</span>
<span class="vi">@bootstrap_nodes</span> <span class="o">=</span> <span class="n">bootstrap_nodes</span>
<span class="vi">@protocol_manage</span> <span class="o">=</span> <span class="n">protocol_manage</span>
<span class="n">server_node_id</span> <span class="o">=</span> <span class="no">NodeID</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@private_key</span><span class="p">)</span>
<span class="n">caps</span> <span class="o">=</span> <span class="p">[</span><span class="no">Cap</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">name: </span><span class="s1">'eth'</span><span class="p">,</span> <span class="ss">version: </span><span class="mi">63</span><span class="p">)]</span>
<span class="vi">@handshake</span> <span class="o">=</span> <span class="no">ProtocolHandshake</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">version: </span><span class="no">BASE_PROTOCOL_VERSION</span><span class="p">,</span> <span class="ss">name: </span><span class="vi">@node_name</span><span class="p">,</span> <span class="ss">id: </span><span class="n">server_node_id</span><span class="p">.</span><span class="nf">id</span><span class="p">,</span> <span class="ss">caps: </span><span class="n">caps</span><span class="p">)</span>
<span class="vi">@tcp_host</span> <span class="o">=</span> <span class="n">tcp_host</span>
<span class="vi">@tcp_port</span> <span class="o">=</span> <span class="n">tcp_port</span>
<span class="vi">@dial</span> <span class="o">=</span> <span class="no">Dial</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">bootstrap_nodes: </span><span class="n">bootstrap_nodes</span><span class="p">,</span> <span class="ss">private_key: </span><span class="n">private_key</span><span class="p">,</span> <span class="ss">handshake: </span><span class="vi">@handshake</span><span class="p">)</span>
<span class="vi">@network_state</span> <span class="o">=</span> <span class="no">NetworkState</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">protocol_manage</span><span class="p">)</span>
<span class="vi">@dial_scheduler</span> <span class="o">=</span> <span class="no">DialScheduler</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@network_state</span><span class="p">,</span> <span class="vi">@dial</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># Introduce a new "shortcut assigning" syntax for convenient setup</span>
<span class="k">class</span> <span class="nc">Person</span>
<span class="c1"># use @ prefix to describe instance variables.</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="vi">@name</span><span class="p">:,</span> <span class="vi">@age</span><span class="p">:,</span> <span class="vi">@gender</span><span class="p">:,</span> <span class="vi">@country</span><span class="p">:)</span>
<span class="k">end</span>
<span class="c1"># equal to</span>
<span class="k">def</span> <span class="nf">initialize2</span><span class="p">(</span><span class="nb">name</span><span class="p">:,</span> <span class="n">age</span><span class="p">:,</span> <span class="n">gender</span><span class="p">:,</span> <span class="n">country</span><span class="p">:)</span>
<span class="vi">@name</span> <span class="o">=</span> <span class="nb">name</span>
<span class="vi">@age</span> <span class="o">=</span> <span class="n">age</span>
<span class="vi">@gender</span> <span class="o">=</span> <span class="n">gender</span>
<span class="vi">@country</span> <span class="o">=</span> <span class="n">country</span>
<span class="k">end</span>
<span class="c1"># it should also work on position style arguments</span>
<span class="k">def</span> <span class="nf">initialize2</span><span class="p">(</span><span class="vi">@name</span><span class="p">,</span> <span class="vi">@age</span><span class="p">,</span> <span class="vi">@gender</span><span class="p">,</span> <span class="vi">@country</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># Our real-world case can be rewritten as below</span>
<span class="k">class</span> <span class="nc">Server</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="vi">@private_key</span><span class="p">:,</span> <span class="vi">@protocol_manage</span><span class="p">:,</span> <span class="vi">@bootstrap_nodes</span><span class="p">:</span> <span class="p">[],</span>
<span class="vi">@node_name</span><span class="p">:</span> <span class="s1">'Ciri'</span><span class="p">,</span> <span class="vi">@tcp_host</span><span class="p">:</span> <span class="s1">'127.0.0.1'</span><span class="p">,</span> <span class="vi">@tcp_port</span><span class="p">:</span> <span class="mi">33033</span><span class="p">)</span>
<span class="n">server_node_id</span> <span class="o">=</span> <span class="no">NodeID</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@private_key</span><span class="p">)</span>
<span class="n">caps</span> <span class="o">=</span> <span class="p">[</span><span class="no">Cap</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">name: </span><span class="s1">'eth'</span><span class="p">,</span> <span class="ss">version: </span><span class="mi">63</span><span class="p">)]</span>
<span class="vi">@handshake</span> <span class="o">=</span> <span class="no">ProtocolHandshake</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">version: </span><span class="no">BASE_PROTOCOL_VERSION</span><span class="p">,</span> <span class="ss">name: </span><span class="vi">@node_name</span><span class="p">,</span> <span class="ss">id: </span><span class="n">server_node_id</span><span class="p">.</span><span class="nf">id</span><span class="p">,</span> <span class="ss">caps: </span><span class="n">caps</span><span class="p">)</span>
<span class="vi">@dial</span> <span class="o">=</span> <span class="no">Dial</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">bootstrap_nodes: </span><span class="vi">@bootstrap_nodes</span><span class="p">,</span> <span class="ss">private_key: </span><span class="vi">@private_key</span><span class="p">,</span> <span class="ss">handshake: </span><span class="vi">@handshake</span><span class="p">)</span>
<span class="vi">@network_state</span> <span class="o">=</span> <span class="no">NetworkState</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@protocol_manage</span><span class="p">)</span>
<span class="vi">@dial_scheduler</span> <span class="o">=</span> <span class="no">DialScheduler</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="vi">@network_state</span><span class="p">,</span> <span class="vi">@dial</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># consider to keep consistency, this "shortcut assigning" syntax should work for non-initialize methods</span>
<span class="k">class</span> <span class="nc">Foo</span>
<span class="k">def</span> <span class="nf">bar</span><span class="p">(</span><span class="vi">@still_works</span><span class="p">)</span>
<span class="nb">p</span> <span class="vi">@still_works</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre> Ruby master - Feature #15112 (Open): Introducing the short form of `STDERR.puts expr.inspect`.https://bugs.ruby-lang.org/issues/151122018-09-13T06:15:38Zmrkn (Kenta Murata)muraken@gmail.com
<p>I sometimes write <code>STDERR.puts obj.inspect</code> to print debug message to standard error.<br>
I want to write it as <code>STDERR.p obj</code>.<br>
It can be realized by introducing <code>p</code> singleton method in <code>STDERR</code> object.</p> Ruby master - Feature #14982 (Open): Improve namespace system in ruby to avoiding top-level name...https://bugs.ruby-lang.org/issues/149822018-08-11T04:26:06Zjjyr (Jinyang Jiang)jjyruby@gmail.com
<p>Updated: <a href="https://bugs.ruby-lang.org/issues/14982#note-5" class="external">https://bugs.ruby-lang.org/issues/14982#note-5</a></p>
<a name="Why"></a>
<h2 >Why<a href="#Why" class="wiki-anchor">¶</a></h2>
<p>Ruby has evaluation all class/module names in top-level context(aka TOPLEVEL_BINDING).<br>
As a user we basically hard to know how many names in the current context, is causing chaos in some cases. For example:</p>
<p>case 1:</p>
<p>Put common used errors class in a single file, like below</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># utils/errors.rb</span>
<span class="k">class</span> <span class="nc">FooError</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">BarError</span>
<span class="k">end</span>
</code></pre>
<p>In other files under 'utils' we want to use those errors, so the best practice is to use <code>require_relative 'errors'</code> in each file we need.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># utils/binary_helper.rb</span>
<span class="c1"># we forget require errors</span>
<span class="k">module</span> <span class="nn">BinaryHelper</span>
<span class="c1"># ...</span>
<span class="k">raise</span> <span class="no">BarError</span>
<span class="c1"># ...</span>
<span class="k">end</span>
</code></pre>
<p>But sometime we may forget to require dependencies in a file, it's hard to notice because<br>
if RubyVM already execute the requires we still can access the name BarError,</p>
<p>but if user directly to require 'utils/binary_helper', he/she will got an NameError.</p>
<p>case 2:</p>
<p>Two gems use same top-level module name, so we can't use them together</p>
<a name="The-Reason-of-The-Problem"></a>
<h2 >The Reason of The Problem<a href="#The-Reason-of-The-Problem" class="wiki-anchor">¶</a></h2>
<p>The reason is we let module author to decision which module user can use. ('require' is basically evaluation, highly dependent on the module author's design)</p>
<p>But we should let users control which names to use and available in context. As many other popular languages dose(Rust, Python..)</p>
<p>I think the solution is basically the same philosophy compares to refinement feature.</p>
<a name="The-Design"></a>
<h2 >The Design<a href="#The-Design" class="wiki-anchor">¶</a></h2>
<p>I propose an improved namespace to Ruby, to solve the problems and still compatible with the current Ruby module system.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Foo</span>
<span class="k">end</span>
<span class="c1"># introduce Kernel#namespace</span>
<span class="n">namespace</span> <span class="ss">:Hello</span> <span class="k">do</span>
<span class="c1"># avoiding namespace chaos</span>
<span class="c1"># Foo -> NameError, can't access TOPLEVEL_BINDING directly</span>
<span class="c1"># Kernel#import method, introduce Foo name from TOPLEVEL_BINDING</span>
<span class="n">import</span> <span class="ss">:Foo</span>
<span class="c1"># in a namespace user can only access imported name</span>
<span class="no">Foo</span>
<span class="c1"># import constant to another alias name</span>
<span class="c1"># can avoid writing nested module/class names</span>
<span class="n">import</span> <span class="ss">:"A::B::C::D"</span><span class="p">,</span> <span class="ss">as: :E</span>
<span class="c1"># require then import, for convenient </span>
<span class="n">import</span> <span class="ss">:"A::B::C::D"</span><span class="p">,</span> <span class="ss">as: :E</span><span class="p">,</span> <span class="ss">from: </span><span class="s1">'some_rb_file'</span>
<span class="c1"># import same name from two gems</span>
<span class="n">import</span> <span class="ss">:"Foo"</span><span class="p">,</span> <span class="ss">as: :Foo_A</span><span class="p">,</span> <span class="ss">from: </span><span class="s1">'foo_a'</span>
<span class="n">import</span> <span class="ss">:"Foo"</span><span class="p">,</span> <span class="ss">as: :Foo_B</span><span class="p">,</span> <span class="ss">from: </span><span class="s1">'foo_b'</span>
<span class="c1"># import names in batch</span>
<span class="n">import</span> <span class="sx">%i{"A::B::C::D", "AnotherClass"}</span><span class="p">,</span> <span class="ss">from: </span><span class="s1">'some_rb_file'</span>
<span class="c1"># import and alias in batch</span>
<span class="n">import</span> <span class="p">{</span><span class="ss">:"A::B::C::D"</span> <span class="o">=></span> <span class="ss">:E</span><span class="p">,</span> <span class="ss">:Foo</span> <span class="o">=></span> <span class="no">Foo2</span><span class="p">},</span> <span class="ss">from: </span><span class="s1">'some_rb_file'</span>
<span class="k">class</span> <span class="nc">Bar</span>
<span class="k">def</span> <span class="nf">xxx</span>
<span class="c1"># can access all names in namespace scope</span>
<span class="p">[</span><span class="no">Foo</span><span class="p">,</span> <span class="no">Foo_A</span><span class="p">,</span> <span class="no">Foo_B</span><span class="p">]</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Hello</span><span class="p">.</span><span class="nf">class</span> <span class="c1"># -> module. namespace is just a module</span>
<span class="no">Hello</span><span class="o">::</span><span class="no">Bar</span> <span class="c1"># so we do not broken current ruby module design</span>
<span class="c1"># namespace system is intent to let user to control names in context</span>
<span class="c1"># So user can choose use the old require way</span>
<span class="nb">require</span> <span class="s1">'hello'</span>
<span class="no">Hello</span><span class="o">::</span><span class="no">Bar</span>
<span class="c1"># Or user can use namespace system as we do in hello.rb</span>
<span class="n">namespace</span> <span class="ss">:Example</span> <span class="k">do</span>
<span class="n">import</span> <span class="ss">:"Hello::Bar"</span><span class="p">,</span> <span class="ss">as: :Bar</span>
<span class="no">Bar</span> <span class="c1"># ok</span>
<span class="no">Foo</span> <span class="c1"># name error, cause we do not import Foo in :Example namespace</span>
<span class="k">end</span>
<span class="no">Foo</span> <span class="c1"># ok, cause Foo is loaded in TOPLEVEL_BINDING</span>
<span class="c1"># define nested namespace</span>
<span class="c1"># more clear syntax than “module Example::NestedExample”</span>
<span class="n">namespace</span> <span class="ss">:NestedExample</span><span class="p">,</span> <span class="ss">under: </span><span class="no">Example</span> <span class="k">do</span>
<span class="k">end</span>
<span class="n">namespace</span> <span class="ss">:Example2</span> <span class="k">do</span>
<span class="n">namespace</span> <span class="ss">:NestedExample</span> <span class="k">do</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Pros:</p>
<ul>
<li>Completely compatible with the current module system, a gem user can completely ignore whether a gem is write in Namespace or not.</li>
<li>User can completely control which names in current context/scope.</li>
<li>May solve the top module name conflict issue(depends on VM implementation).</li>
<li>Avoid introducing new keyword and syntax.</li>
<li>Type hint or name hint can be more accuracy under namespace(not sure).</li>
</ul>
<p>Cons:</p>
<ul>
<li>Need to modify Ruby VM to support the feature.</li>
</ul> Ruby master - Feature #14927 (Open): Loading multiple files at oncehttps://bugs.ruby-lang.org/issues/149272018-07-20T18:13:55ZAnonymous
<p>Just a proof concept I wanted to share. Maybe it could be useful?</p>
<p>Say you want to load all the .rb files in your lib directory:</p>
<pre><code class="ruby syntaxhl" data-language="ruby">
<span class="no">Dir</span><span class="p">[</span><span class="s1">'lib/**/*.rb'</span><span class="p">].</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span> <span class="nb">load</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="p">}</span>
</code></pre>
<p>This approach may not work if your files have dependencies like that:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># lib/foo.rb</span>
<span class="k">class</span> <span class="nc">Foo</span> <span class="o"><</span> <span class="no">Bar</span>
<span class="k">end</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># lib/bar.rb</span>
<span class="k">class</span> <span class="nc">Bar</span>
<span class="k">end</span>
</code></pre>
<p>Foo class needs Bar class. You will get a NameError (uninitialized constant Bar).</p>
<p>So in my personal projects, I use this algorithm to load all my files and to automatically take care of dependencies (class/include):</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">boot</span><span class="p">(</span><span class="n">files</span><span class="p">)</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">i</span> <span class="o"><</span> <span class="n">files</span><span class="p">.</span><span class="nf">length</span>
<span class="k">begin</span>
<span class="nb">load</span><span class="p">(</span><span class="n">files</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
<span class="k">rescue</span> <span class="no">NameError</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">else</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">></span> <span class="mi">0</span>
<span class="n">files</span><span class="p">.</span><span class="nf">push</span><span class="p">(</span><span class="n">files</span><span class="p">.</span><span class="nf">shift</span><span class="p">)</span>
<span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">end</span>
<span class="n">files</span><span class="p">.</span><span class="nf">shift</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby">
<span class="n">boot</span> <span class="no">Dir</span><span class="p">[</span><span class="s1">'lib/**/*.rb'</span><span class="p">]</span> <span class="c1"># It works! foo.rb and bar.rb are properly loaded.</span>
</code></pre>
<p>My point is: it would be cool if Kernel#load could receive an array of filenames (to load all these files in the proper order). So we could load all our libs with just a single line:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">load</span> <span class="no">Dir</span><span class="p">[</span><span class="s1">'{path1,path2}/**/*.rb'</span><span class="p">]</span>
</code></pre> Ruby master - Misc #14760 (Open): cross-thread IO#close semanticshttps://bugs.ruby-lang.org/issues/147602018-05-15T10:04:52Znormalperson (Eric Wong)normalperson@yhbt.net
<p>I wrote about cross-thread IO#close in ruby-core, but I'm not sure if it's a bug<br>
or not to have missing support for IO.select and IO.copy_stream:</p>
<p>IO.select -<br>
<a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/86655" class="external">http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/86655</a><br>
<a href="https://public-inbox.org/ruby-core/20180423133946.GA6019@dcvr/" class="external">https://public-inbox.org/ruby-core/20180423133946.GA6019@dcvr/</a></p>
<p>IO.copy_stream -<br>
<a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/87040" class="external">http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/87040</a><br>
<a href="https://public-inbox.org/ruby-core/20180515095315.GA15909@dcvr/" class="external">https://public-inbox.org/ruby-core/20180515095315.GA15909@dcvr/</a></p>
<p>I know the IO.select case in 1.9+ differs from 1.8, and IO.copy_stream wasn't in<br>
1.8, but I guess the current behavior is that it isn't consistent with normal IO<br>
methods. IO.copy_stream will also behave "normally" and raise IOError if it<br>
somehow hits non-optimized cases and ends up calling Ruby methods, but my<br>
example in <a href="https://blade.ruby-lang.org/ruby-core/87040">[ruby-core:87040]</a> did not hit that case.</p>
<p>On one hand, I'm not a fan of "nanny features" like deadlock detection for<br>
threading. On the other hand, I value consistency and we already went down the<br>
rabbit hole of supporting current users of rb_thread_io_blocking_region.</p>
<p>Anyways, I can implement these if desired since I have additional work planned<br>
in this area anyways (auto-fiber).</p> Ruby master - Feature #14724 (Open): chains of inequalitieshttps://bugs.ruby-lang.org/issues/147242018-04-30T06:36:57Zgotoken (Kentaro Goto)gotoken@gmail.com
<p>In mathematics, chain of inequations is a shorthand notation for the conjunction of several inequations involving common expressions.</p>
<p>For example, <code>a < b <= c</code> for <code>a < b && b <= c</code></p>
<p>Chain notation makes code clearer, in particular, long common expression cases will be so. E.g.,</p>
<pre><code>cur.to_i - 2 <= timeval.tv_sec <= cur.to_i
</code></pre>
<p>is easier to read than</p>
<pre><code>cur.to_i - 2 <= timeval.tv_sec && timeval.tv_sec <= cur.to_i
</code></pre>
<p>because in the latter case we have to verify whether <code>timeval.tv_sec</code> is common or not by eyes.</p>
<p>Current syntax allows but redefining builtin methods are considered not practical. So here I request as a new syntax for the chains.</p>
<a name="Use-cases-applicable-conjunctions"></a>
<h3 >Use cases (applicable conjunctions)<a href="#Use-cases-applicable-conjunctions" class="wiki-anchor">¶</a></h3>
<p>lib/matrix.rb:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">unless</span> <span class="mi">0</span> <span class="o"><=</span> <span class="n">column</span> <span class="o">&&</span> <span class="n">column</span> <span class="o"><</span> <span class="n">column_count</span>
</code></pre>
<p>lib/time.rb documents:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="c1"># block. For example:</span>
<span class="c1">#</span>
<span class="c1"># Time.parse(...) {|y| 0 <= y && y < 100 ? (y >= 69 ? y + 1900 : y + 2000) : y}</span>
</code></pre>
<p>spec/ruby/optional/capi/bignum_spec.rb:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">raise</span> <span class="s2">"Bignum#coerce returned Fixnum"</span> <span class="k">if</span> <span class="n">fixnum_min</span> <span class="o"><=</span> <span class="n">n</span> <span class="o">&&</span> <span class="n">n</span> <span class="o"><=</span> <span class="n">fixnum_max</span>
</code></pre>
<p>test/fiddle/test_import.rb:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="n">assert</span><span class="p">(</span><span class="n">cur</span><span class="p">.</span><span class="nf">to_i</span> <span class="o">-</span> <span class="mi">2</span> <span class="o"><=</span> <span class="n">timeval</span><span class="p">.</span><span class="nf">tv_sec</span> <span class="o">&&</span> <span class="n">timeval</span><span class="p">.</span><span class="nf">tv_sec</span> <span class="o"><=</span> <span class="n">cur</span><span class="p">.</span><span class="nf">to_i</span><span class="p">)</span>
</code></pre>
<p>tool/jisx0208.rb:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">unless</span> <span class="mh">0x8140</span> <span class="o"><=</span> <span class="n">sjis</span> <span class="o">&&</span> <span class="n">sjis</span> <span class="o"><=</span> <span class="mh">0xFCFC</span>
</code></pre> Ruby master - Feature #14609 (Open): Let `Kernel#p` without an argument print the receiverhttps://bugs.ruby-lang.org/issues/146092018-03-16T01:29:09Zko1 (Koichi Sasada)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p><code>Kernel#p(obj)</code> prints <code>obj</code> as <code>inspect</code>ed.<br>
How about printing the receiver if an argument is not given?</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>We recently introduced <code>yield_self</code>, which encourages block chain.</p>
<p><a href="https://zverok.github.io/blog/2018-01-24-yield_self.html" class="external">https://zverok.github.io/blog/2018-01-24-yield_self.html</a><br>
Quoting from this article, we can write method chain with blocks:</p>
<pre><code>construct_url
.yield_self { |url| Faraday.get(url) }.body
.yield_self { |response| JSON.parse(response) }
.dig('object', 'id')
.yield_self { |id| id || '<undefined>' }
.yield_self { |id| "server:#{id}" }
</code></pre>
<p>There is a small problem concerning debugging.<br>
If we want to see the intermediate values in the method/block chain, we need to insert <code>tap{|e| p e}</code>.</p>
<p>With the above example,</p>
<pre><code>construct_url
.yield_self { |url| Faraday.get(url) }.body
.yield_self { |response| JSON.parse(response) }.tap{|e| p e} # debug print
.dig('object', 'id')
.yield_self { |id| id || '<undefined>' }.tap{|e| p e} # debug print
.yield_self { |id| "server:#{id}" }
</code></pre>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>Let <code>obj.p</code> work the same as <code>p(obj)</code>.</p>
<p>We can replace<br>
<code>block{...}.tap{|e| p e}</code><br>
with<br>
<code>block{...}.p</code></p>
<p>For the above example, we can simply add <code>.p</code> at the end of a line:</p>
<pre><code>construct_url
.yield_self { |url| Faraday.get(url) }.body
.yield_self { |response| JSON.parse(response) }.p # debug print
.dig('object', 'id')
.yield_self { |id| id || '<undefined>' }.p # debug print
.yield_self { |id| "server:#{id}" }
</code></pre>
<a name="Compatibility-issues"></a>
<h1 >Compatibility issues<a href="#Compatibility-issues" class="wiki-anchor">¶</a></h1>
<p>(1) Shorthand for <code>nil</code></p>
<p>This spec change can introduce compatibility issues because <code>p</code> returns <code>nil</code> and does not output anything.<br>
That is to say, <code>p</code> is a shorthand for <code>nil</code>. Some code-golfers use it.</p>
<p>Maybe we can ignore them :p</p>
<p>(2) make it a public method</p>
<p><code>Kernel#p</code> a is private method, so if we mistype <code>obj.x</code> as <code>obj.p</code> (not sure how it is feasible), it will raise a <code>NoMethodError</code> because of visibility.<br>
We need to change this behavior.</p>
<a name="Note"></a>
<h1 >Note<a href="#Note" class="wiki-anchor">¶</a></h1>
<a name="Past-proposal-and-discussion"></a>
<h2 >Past proposal and discussion<a href="#Past-proposal-and-discussion" class="wiki-anchor">¶</a></h2>
<p>Endoh-san proposed the same idea 10+ years ago <a href="https://blade.ruby-lang.org/ruby-dev/29736">[ruby-dev:29736]</a> in Japanese.<br>
I think we should revisit this idea because of <code>yield_self</code> introduction.</p>
<p>In this thread, Matz said "simple <code>p</code> shows <code>p(self)</code>, it is not clear".</p>
<p><a href="https://blade.ruby-lang.org/ruby-dev/30903">[ruby-dev:30903]</a></p>
<pre><code> p
はどう動くのかとか(p selfと同じ、は変な気が)
self.p(obj)
はどうなのかとか。その辺が解決(納得)できたら、ということで。
</code></pre>
<p>English translation:</p>
<pre><code>What would the behavior of:
p
be? (I feel strange for it to be equivalent to `p(self)`.) What would happen to
self.p(obj)
</code></pre>
<a name="pp"></a>
<h2 >pp<a href="#pp" class="wiki-anchor">¶</a></h2>
<p>If this proposal is accepted, we also need to change the behavior of <code>pp</code>.</p>
<a name="gems"></a>
<h2 >gems<a href="#gems" class="wiki-anchor">¶</a></h2>
<p><code>tapp</code> method is provided by a gem.<br>
<a href="https://github.com/esminc/tapp" class="external">https://github.com/esminc/tapp</a></p>
<p>I thought about proposing this method in core. But I found that <code>p</code> is shorter than <code>tapp</code>.<br>
A disadvantage is that <code>p</code> is too short and difficult to grep.</p> Ruby master - Feature #14548 (Open): Allow some_array&.[1] to be a valid syntaxhttps://bugs.ruby-lang.org/issues/145482018-02-23T19:59:34Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<p>Currently, Ruby allows accessing an array's index while testing whether the array is not nil with this syntax: <code>my_array&.[](1)</code>. I've always found this awkward but didn't mind about suggesting anything to improve this.</p>
<p>I was just reading about how JavaScript is probably going to support myArray?.[1] and found that it read good enough for me.</p>
<p>So I'd like to propose about the same syntax, replacing ?. with the Ruby equivalent &. instead. How does that look like to you?</p> Ruby master - Feature #14546 (Open): Hash#delete!https://bugs.ruby-lang.org/issues/145462018-02-23T18:52:02Zrringler (Ryan Ringler)
<p>Hash#delete currently returns nil if a given key is not found in the hash. It would be nice to have a way to check that the key was present in the hash. This can be accomplished with with a block, but it would be nice to have some sugar for this.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">{</span> <span class="ss">a: </span><span class="s1">'a'</span> <span class="p">}.</span><span class="nf">delete</span><span class="p">(</span><span class="ss">:b</span><span class="p">)</span> <span class="c1"># => nil</span>
<span class="p">{</span> <span class="ss">a: </span><span class="s1">'a'</span> <span class="p">}.</span><span class="nf">delete</span><span class="p">(</span><span class="ss">:b</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">key</span><span class="o">|</span> <span class="k">raise</span> <span class="no">KeyError</span><span class="p">,</span> <span class="s2">"key not found </span><span class="si">#{</span><span class="n">key</span><span class="si">}</span><span class="s2">"</span> <span class="p">}</span> <span class="c1"># => KeyError (key not found: b)</span>
</code></pre>
<p>I'd like to propose a Hash#delete! method:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">{</span> <span class="ss">a: </span><span class="s1">'a'</span> <span class="p">}.</span><span class="nf">delete!</span><span class="p">(</span><span class="ss">:a</span><span class="p">)</span> <span class="c1"># => 'a'</span>
<span class="p">{</span> <span class="ss">a: </span><span class="s1">'a'</span> <span class="p">}.</span><span class="nf">delete!</span><span class="p">(</span><span class="ss">:b</span><span class="p">)</span> <span class="c1"># => KeyError (key not found: :b)</span>
</code></pre> Ruby master - Feature #14128 (Open): Introduce Hash#delete default valuehttps://bugs.ruby-lang.org/issues/141282017-11-23T14:18:23Zgshutler (Garry Shutler)
<p>Mirror <code>Hash#fetch(key [, default]) → obj</code> with <code>Hash#delete(key [, default]) → obj</code>.</p>
<p>Allows for more concise extraction of a value from a hash with a default.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Currently</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">hash</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="ss">:a</span><span class="p">)</span> <span class="p">{</span> <span class="mi">10</span> <span class="p">}</span>
<span class="c1"># Becomes</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">hash</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="ss">:a</span><span class="p">,</span> <span class="mi">10</span><span class="p">)</span>
</code></pre> Ruby master - Feature #12306 (Open): Implement String #blank? #present? and improve #strip and fa...https://bugs.ruby-lang.org/issues/123062016-04-20T23:33:04Zsam.saffron (Sam Saffron)sam.saffron@gmail.com
<p>Time and again there have been rejected feature requests to Ruby core to implement <code>blank</code> and <code>present</code> protocols across all objects as ActiveSupport does. I am fine with this call and think it is fair.</p>
<p>However, for the narrow case of String having <code>#blank?</code> and <code>#present?</code> makes sense.</p>
<ul>
<li>
<p>Provides a natural extension over <code>#strip</code>, <code>#lstrip</code> and <code>#rstrip</code>. <code>(" ".strip.length == 0) == " ".blank?</code></p>
</li>
<li>
<p>Plays nicely with ActiveSupport, providing an efficient implementation in Ruby core: see: <a href="https://github.com/SamSaffron/fast_blank" class="external">https://github.com/SamSaffron/fast_blank</a>, implementing blank efficiently requires a c extension.</p>
</li>
</ul>
<p>However, if this work is to be done, <code>#strip</code> and should probably start dealing with unicode blanks, eg:</p>
<pre><code>irb(main):008:0> [0x3000].pack("U")
=> " "
irb(main):009:0> [0x3000].pack("U").strip.length
=> 1
</code></pre>
<p>So there are 2 questions / feature requests here</p>
<ol>
<li>Can we add blank? and present? to String?</li>
<li>Can we amend strip and family to account for unicode per: <a href="https://github.com/SamSaffron/fast_blank/blob/master/ext/fast_blank/fast_blank.c#L43-L74" class="external">https://github.com/SamSaffron/fast_blank/blob/master/ext/fast_blank/fast_blank.c#L43-L74</a>
</li>
</ol> Ruby master - Feature #12244 (Open): Add a way to `integer - integer % num`https://bugs.ruby-lang.org/issues/122442016-04-02T13:45:33Znaruse (Yui NARUSE)naruse@airemix.jp
<p>We sometimes calculates <code>integer - integer % num</code>.</p>
<p>For example time series events into time partitions, we write code like</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">event</span> <span class="c1"># {time: 1459580435, name: "hoge", text: "Rawr!"}</span>
<span class="n">partition</span> <span class="o">=</span> <span class="n">event</span><span class="p">[</span><span class="ss">:time</span><span class="p">]</span> <span class="o">-</span> <span class="n">event</span><span class="p">[</span><span class="ss">:time</span><span class="p">]</span> <span class="o">%</span> <span class="n">num</span>
<span class="n">chunk</span> <span class="o">=</span> <span class="n">get_chunk</span><span class="p">(</span><span class="n">partition</span><span class="p">)</span>
<span class="n">chunk</span><span class="p">.</span><span class="nf">write</span> <span class="n">event</span>
</code></pre>
<p><a href="https://twitter.com/tagomoris/status/715814050534461440" class="external">https://twitter.com/tagomoris/status/715814050534461440</a><br>
<a href="https://twitter.com/tagomoris/status/715814961260457985" class="external">https://twitter.com/tagomoris/status/715814961260457985</a></p>
<p>The name is always issue.<br>
There are some suggestions likes Integer#adjust](<a href="https://twitter.com/cocoatomo/status/716088708655489024" class="external">https://twitter.com/cocoatomo/status/716088708655489024</a>).</p>
<p>kosaki says <a href="https://twitter.com/kosaki55tea/status/716059296186765312" class="external">Excel's FLOOR() function is FLOOR(number, significance)</a>.<br>
Therefore Ruby should be <a href="https://twitter.com/kosaki55tea/status/716106530114768897" class="external">Integer#floor(digits=1, significance: nil)</a>.<br>
<a href="https://twitter.com/kosaki55tea/status/716107516409581568" class="external">kosaki agrees this</a>.</p>
<p>I checked the speed of a half baked implementation..., but it's 10x slow...</p>
<pre><code>% time ./miniruby -e'i=10000000;while i>0;i-=1;1459497599.floor(significance: 3600);end'
./miniruby 6.58s user 0.02s system 99% cpu 6.596 total
#3 1459604131 22:35:31 naruse@windy:~/obj/ruby
% time ./miniruby -e'i=10000000;while i>0;i-=1;t=1459497599;t-t%3600;end'
./miniruby -e'i=10000000;while i>0;i-=1;t=1459497599;t-t%3600;end' 0.52s user 0.00s system 99% cpu 0.520 total
</code></pre>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/numeric.c b/numeric.c
index 37217a1..f6acfe3 100644
</span><span class="gd">--- a/numeric.c
</span><span class="gi">+++ b/numeric.c
</span><span class="p">@@ -4123,6 +4123,42 @@</span> int_dotimes(VALUE num)
<span class="err">
</span> /*
* call-seq:
<span class="gi">+ * int.floor([ndigits]) -> integer or float
+ *
+ * Rounds +int+ to a given precision in decimal digits (default 0 digits).
+ *
+ * Precision may be negative. Returns a floating point number when +ndigits+
+ * is positive, +self+ for zero, and round down for negative.
+ *
+ * 1.round #=> 1
+ * 1.round(2) #=> 1.0
+ * 15.round(-1) #=> 20
+ */
+
+static VALUE
+int_floor(int argc, VALUE* argv, VALUE num)
+{
+ static ID keyword_ids[1];
+ VALUE kwargs[1], ndigits, opt;
+ if (!keyword_ids[0]) {
+ CONST_ID(keyword_ids[0], "significance");
+ }
+
+ rb_scan_args(argc, argv, "01:", &ndigits, &opt);
+ if (!NIL_P(opt)) {
+ VALUE factor;
+ long a, b;
+ rb_get_kwargs(opt, keyword_ids, 0, 1, kwargs);
+ factor = kwargs[0];
+ a = FIX2LONG(num);
+ b = FIX2LONG(factor);
+ return LONG2FIX(a - a % b);
+ }
+ return Qnil;
+}
+
+/*
+ * call-seq:
</span> * int.round([ndigits]) -> integer or float
*
* Rounds +int+ to a given precision in decimal digits (default 0 digits).
<span class="p">@@ -4321,7 +4357,7 @@</span> Init_Numeric(void)
rb_define_method(rb_cInteger, "to_i", int_to_i, 0);
rb_define_method(rb_cInteger, "to_int", int_to_i, 0);
rb_define_method(rb_cInteger, "to_f", int_to_f, 0);
<span class="gd">- rb_define_method(rb_cInteger, "floor", int_to_i, 0);
</span><span class="gi">+ rb_define_method(rb_cInteger, "floor", int_floor, -1);
</span> rb_define_method(rb_cInteger, "ceil", int_to_i, 0);
rb_define_method(rb_cInteger, "truncate", int_to_i, 0);
rb_define_method(rb_cInteger, "round", int_round, -1);
</code></pre> Ruby master - Feature #12019 (Open): Better low-level support for writing concurrent librarieshttps://bugs.ruby-lang.org/issues/120192016-01-25T19:16:25Zpitr.ch (Petr Chalupa)
<p>Nowadays, almost every processor has more than one core. Therefore it becomes more and more important for languages to have good support of concurrent and/or parallel computation. Currently Ruby supports concurrency mainly through high-level classes: <code>Thread</code>, <code>Queue</code>, <code>Mutex</code>, <code>Monitor</code>, <code>ConditionVariable</code>.</p>
<p>This work is not colliding with plans for Ruby 3 (to provide an easy-to-use and safe concurrent abstraction to Ruby users). Following proposals suggest several key low-level Ruby extensions which will allow those interested in these topics to create fast concurrency abstractions (gems) for Ruby community, providing more choices and complementing the effort of Ruby 3. The proposed APIs are not expected to be used for every day programming but rather by concurrency enthusiast.</p>
<p>This issue is intended to serve as an aggregator for other various proposals described in following issues.</p> Ruby master - Feature #11882 (Open): Map or NamedMaphttps://bugs.ruby-lang.org/issues/118822015-12-26T20:28:30Zhcatlin (Hampton Catlin)hcatlin@gmail.com
<p>Hash is one of the best features of Ruby. I remember being so pleased when I first learned Ruby to find out that <em>anything</em> could be a key and that you could do some really clever things with scripts, if you key of non-traditional elements.</p>
<p>However, like many people, 10 years into using Ruby, I still am writing code to cast around symbols to strings and strings to symbols, just to use Hash as a more traditional dictionary, keyed with string-like values. And, explaining to a junior programmers why they broke the code by using a key of a different type... it's not the most elegant thing to have to explain over and over.</p>
<p>Several proposals exist for how to deal with this, and all have been rejected... however it doesn't seem like it's for essential reasons, more technical or syntactic issues. Coming up with syntax is something I quite enjoy (Sass/Haml), so I thought I'd make a pitch for it.</p>
<p>Requirements:</p>
<ol>
<li>Doesn't break existing code</li>
<li>Doesn't totally destroy the parser</li>
<li>Seems simple to differentiate</li>
<li>Clear upgrade path</li>
</ol>
<p>My proposal is to introduce an entirely different type of Hash, called a Map (or NamedMap, if that's too ambiguous), that requires a string-like key. There are no other types of keys allowed on this Hash, other than either strings or symbols. Internally, each key would be considered a symbol only.</p>
<pre><code>map = Map.new(a: 2, b: 3)
map["a"] #=> 2
map[:a] #=> 2
</code></pre>
<p>Already, we're better than HashWithIndifferentAccess, as it's clearly a bit easier to type. ;)</p>
<p>What about a literal syntax?</p>
<pre><code>map = {{a: 2}}
empty_map = {{}}
</code></pre>
<p>As far as I can tell in the Ruby-syntax style, this should be pretty easy to distinguish syntactically from both a regular hash literal and a block. Further, as almost every method's option hash is string-keyed, you could easily define this.</p>
<pre><code>def my _method(arg1, options = {{}})
end
</code></pre>
<p>Immediately, you could deal with your options hash, and not have to stress about if the end user has passed in strings or symbols into the options.</p>
<p>It would be trivial to create a Map polyfill for most libraries to start using the non-literal version right away, as it would basically be HashWithIndifferentAccess, except we need to guarantee that the keys are string-like.</p>
<p>So, to sum up, we avoid the 'breaking other people's existing code' by introducing a new data-type, the literal syntax (I think) should be fairly easy to implement, and it makes a very natural keyed data object (e.g. Javascript Objects) and brings that to Ruby.</p> Ruby master - Feature #11735 (Open): Porting String#squish and String#squish! from Ruby on Rails'...https://bugs.ruby-lang.org/issues/117352015-11-24T19:36:33Zsikachu (Prem Sichanugrist)s+ruby@sikac.hu
<p>Hi,</p>
<p>I have been using this <code>String#squish</code> method so many time when I'm using Rails, and I think it should be a useful addition to core.</p>
<p>Here's the method on Rails' documentation: <a href="http://api.rubyonrails.org/v4.2.5/classes/String.html#method-i-squish" class="external">http://api.rubyonrails.org/v4.2.5/classes/String.html#method-i-squish</a></p>
<p>This method is very useful when you have to write a multi-line string using heredoc, but you actually does not care about the white-spaces before, after, and in-between the string.</p>
<p>For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o"><<-</span><span class="no">SQL</span><span class="p">.</span><span class="nf">squish</span><span class="sh">
SELECT *
FROM users
WHERE users.username = 'sikachu'
</span><span class="no">SQL</span>
<span class="c1">#=> "SELECT * FROM users WHERE users.username='sikachu'"</span>
</code></pre>
<p>Another example usage is when you are on the project that have a line length code standard, and you have to write a long warning message that needs to be printed to stdout:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">puts</span> <span class="o"><<-</span><span class="no">WARNING</span><span class="p">.</span><span class="nf">squish</span><span class="sh">
Unable to connect to the server. Please double-check that you are currently
connecting to the internet and your proxy server is working.
</span><span class="no">WARNING</span>
<span class="c1">#=> Unable to connect to the server. Please double-check that you are currently connecting to the internet and your proxy server is working.</span>
</code></pre>
<p>By the way, this is my first patch and my first time writing something in C, so there might be something that does not look right to you. I'll happy to revise this patch (and learn about C in the process!) from your feedback.</p>
<p>Thank you,<br>
Prem</p> Ruby master - Feature #11627 (Open): make `nonzero` an alias of `nonzero?`https://bugs.ruby-lang.org/issues/116272015-10-27T23:00:34ZAnonymous
<p>for historic reasons <code>nonzero?</code> returns self or nil. (according to <a href="https://bugs.ruby-lang.org/issues/9123" class="external">https://bugs.ruby-lang.org/issues/9123</a>)</p>
<p>I like the expectation that <code>method?</code> returns true and false.<br>
That <code>nonzero?</code> returns only truthy/falsy values would be fine, except using its return values are <em>useful</em>.</p>
<p><code>value.nonzero? || calculation</code> or <code>(a <=> b).nonzero? || a.subvalue <=> b.subvalue</code></p>
<p>I would feel more comfortable with <code>value.nonzero || calculation</code> even though it is only one character different.</p>
<p>Yes, it's a small thing, but I like ruby for the small things :)</p>
<p>Thanks.</p> Ruby master - Feature #11518 (Open): Queue enhancement - promote! and promote_all!https://bugs.ruby-lang.org/issues/115182015-09-09T15:04:58Zjonathanscruz (Jonathan Cruz)jonathanscruz@yahoo.com
<p>I’m submitting a patch to enhance the Queue class by adding the methods Queue#promote! and Queue#promote_all!. These methods require a block that accepts queue elements. Elements for which the block returns a truthy value are moved to the ‘front’ of the queue. Queue#promote! only applies to the first such element and Queue#promote_all! applies to all matching elements (preserving their relative order).</p>
<p>Motivation for this enhancement: Our project has several worker threads working on long-running work units in a queue, trying to find a ‘match’. The queue is pre-sorted with the most likely matches at the front and least likely at the back. However, there are cases where as we work on some elements, we gain new data that certain elements are more likely to match than we originally thought. We need a way to promote these elements to the front of the queue.</p> Ruby master - Feature #11517 (Open): Queue enhancement - conditional pophttps://bugs.ruby-lang.org/issues/115172015-09-09T15:03:32Zjonathanscruz (Jonathan Cruz)jonathanscruz@yahoo.com
<p>I’m submitting a patch to enhance Queue#pop. This allows the caller to provide a block that accepts data from the queue. Queue#pop will return the first element for which the block returns a truthy value, and remove it from the queue. Without a block, Queue#pop will behave the same way it currently does.</p>
<p>The motivation for this enhancement: On our project, we have a queue of work and several worker threads. Some work can incur a heavy load on the system and should not be processed while another worker is processing 'heavy load' work. We need a way for Queue#pop to skip over heavy load items while another thread is processing heavy load work.</p> Ruby master - Feature #11390 (Open): Allow symbols starting with numbershttps://bugs.ruby-lang.org/issues/113902015-07-22T19:32:50Zv0dro (Sameer Deshmukh)sameer.deshmukh93@gmail.com
<p>Currently it is not possible to create a symbol that looks like <code>:1twothree</code>.</p>
<p>Converting to a string and then symbolizing causes hash lookup problems and proves counter-intuitive. What's also surprising is that ruby allows symbols to start with special characters but not numbers.</p> Ruby master - Feature #11307 (Open): exception-free non-blocking Queue#pophttps://bugs.ruby-lang.org/issues/113072015-06-25T23:06:21Znormalperson (Eric Wong)normalperson@yhbt.net
<p>As we learned from the nonblocking IO APIs, exceptions are noisy with debugging<br>
enabled and waste allocations on backtraces. We should have a better way to do<br>
non-blocking Queue#pop without raising exceptions, but I don't know what the API<br>
should be...</p> Ruby master - Feature #11181 (Open): Add a line directive to Rubyhttps://bugs.ruby-lang.org/issues/111812015-05-26T07:05:18Zgam3 (Allen Morris)gam3-ruby@gam3.net
<p>Add a <strong>line directive</strong> to Ruby</p>
<pre><code> #line {nn} ["filename"]
</code></pre>
<p>This is done by creating a array of filenames and using the upper bits of the line_number to determine the current filename. The original filename is in position 0.</p>
<p>An extra node is added by the parser that informs the compiler of the filenames so the backtrace code can also use the correct file names.</p>
<p>The <strong>__LINE</strong>__ and <strong>__FILE</strong>__ <em>constants</em> are updated and compile time warnings are also effected.</p>
<p>There is a pull request at <a href="https://github.com/ruby/ruby/pull/911" class="external">https://github.com/ruby/ruby/pull/911</a></p>
<p>The patch does not have any affect on current programs unless a line matching '#\s<em>line \d+(\s+"(.</em>)")?\s*$' is found in the ruby source code.</p>
<p>More tests need to be written before this change sould be applied.</p>
<p>Use case:</p>
<p>This is helpful for debugging any generated code but is particularlly helpful for literate programming using Noweb.</p> Ruby master - Feature #11122 (Open): exception-free non-blocking Queue/SizedQueue operationshttps://bugs.ruby-lang.org/issues/111222015-05-06T20:53:09Znormalperson (Eric Wong)normalperson@yhbt.net
<p>I would like to reduce exceptions for non-blocking operations on<br>
Queue/SizedQueue in the same way we are reducing exceptions for non-blocking<br>
I/O with *_nonblock(..., exception: false) methods.</p>
<p>However, I'm unclear what the API would be, since queues return Ruby objects<br>
instead of String buffers or number of bytes written, so any special<br>
object/symbol we would return could conflict with existing applications.</p>
<p>Perhaps something like:</p>
<pre><code>queue.pop(nonblock: :WAIT)
queue.push(obj, nonblock: :WAIT)
</code></pre>
<p>Which would allow user to specify which object to raise when a queue is empty<br>
or full (similar to Timeout.timeout allowing specific exception to raise).</p> Ruby master - Feature #11028 (Assigned): standalone running single file ( zipped archives of ruby...https://bugs.ruby-lang.org/issues/110282015-04-03T03:44:09Zzaxebo1 (zaxebo zaxebo)zaxebo1@gmail.com
<p>standalone running single file ( zipped archives of ruby code) running <strong>without installation</strong> using "gem install ..."<br>
prior examples in other languages:</p>
<pre><code>python myprg.pyz
java -jar myprg.jar
</code></pre>
<a name="Detailed-Description"></a>
<h2 >Detailed Description:<a href="#Detailed-Description" class="wiki-anchor">¶</a></h2>
<p>In python, if i have multiple program files: "<code>a1.py</code>, <code>a2.py</code>, <code>__main__.py</code>,<br>
<code>dir1/b1.py</code>, <code>dir1/b2.py</code>" and then i zip it as myprogram1.pyz<br>
then i can run it as "python myprogram.pyz" (<code>__main__.py</code> inside the zip<br>
file will be executed first). It is easy to distribute a single file<br>
myprogram1.pyz</p>
<p>see: <a href="http://blogs.gnome.org/jamesh/2012/05/21/python-zip-files/" class="external">http://blogs.gnome.org/jamesh/2012/05/21/python-zip-files/</a></p>
<hr>
<p>in java also we can bundle all the .class files into a single .jar file<br>
and run it</p>
<pre><code>java -jar myprogram1.jar
</code></pre>
<hr>
<p>Currently in ruby the ".gem" file requires installation using "gem install ...". Then it gives some program file for running.<br>
What i am asking is that some gem file should have manifest with which they can run directly without installing</p>
<p>That is, i request you to kind provide a feature in ruby that if i have lots of files like: <code>a1.rb</code>, <code>a2.rb</code>, <code>__main__.rb</code>, <code>dir1/a4.rb</code> etc.<br>
(say, which uses Ruby-GTK for a Desktop application). Then i should be able to bundle them as zip file, say myprog1.zip or myprog1.pz ( rbz=ruby's zipped executable archive).<br>
And then i can distribute this "single file" and execute it as:</p>
<pre><code>ruby myprog1.rbz
</code></pre>
<p>This will execute the <code>__main__.rb</code> file among all the other .rb files,<br>
inside this .zip archive myprog1.rbz .<br>
Note: this .rbz file extension can be .gemz or whatever, but this functionality of "standalone running zipped archives of ruby code running without installation" is essential</p> Ruby master - Feature #10574 (Open): Add String#lchomp and String.lchomp!https://bugs.ruby-lang.org/issues/105742014-12-05T20:37:41Zjavawizard (Alex Boyd)alex@opengroove.org
<p>With the expected behavior, i.e.</p>
<pre><code>irb(main):013:0> 'foobar'.lchomp('foo')
=> "bar"
irb(main):014:0> 'foobar'.lchomp('baz')
=> "foobar"
</code></pre>
<p>A quick google search will turn up plenty of practical uses for this, as well as lots of libraries that patch <code>String</code> themselves to add this.</p> Ruby master - Feature #10549 (Open): Deprecate each_with_index and each_with_object in favor of w...https://bugs.ruby-lang.org/issues/105492014-11-26T16:12:04Zdanielmorrison (Daniel Morrison)daniel@collectiveidea.com
<p>I wonder if we can deprecate <code>each_with_index</code> and <code>each_with_object</code> and fully recommend <code>with_index</code> and <code>with_object</code> instead.</p>
<p>I personally like the shorter forms because they hint that they can be used with more methods than simply <code>each</code>. People don't need to ask if there's a <code>map_with_index</code> method, they can just try chaining it the same way and it works! I realized this when teaching new Rubyists, because they often ask those questions.</p>
<p>There is a negligible performance hit.</p>
<p>Lots of code uses <code>each_with_index</code> but it is a one-character change to use <code>each.with_index</code> instead.</p>
<p>Forgive me if this has been brought up recently, but I couldn't find any discussion on it.</p> Ruby master - Misc #10541 (Open): Remove shorthand string interpolation syntaxhttps://bugs.ruby-lang.org/issues/105412014-11-25T16:15:58Zdanielmorrison (Daniel Morrison)daniel@collectiveidea.com
<p>I would like to see the shorthand string interpolation syntax, "foo#@bar" deprecated and then removed in 3.0.</p>
<p>My reasons:</p>
<ol>
<li>Most experienced Ruby developers I've talked to don't even know it exists.</li>
<li>It has been the cause of real problems. <a href="http://status.cloudamqp.com/incidents/vj62pnp62tj9" class="external">http://status.cloudamqp.com/incidents/vj62pnp62tj9</a>
</li>
</ol>
<p>When a syntax is not widely known and has the potential for problems, I think it makes sense to deprecate and remove.</p> Ruby master - Feature #10498 (Open): Make `loop` yield a counterhttps://bugs.ruby-lang.org/issues/104982014-11-12T06:33:46Zcesario (Franck Verrot)franck@verrot.fr
<a name="Problem"></a>
<h1 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h1>
<p>Teaching Ruby, we always end up with that type of construct</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="kp">loop</span> <span class="k">do</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="c1"># do something with i....</span>
<span class="k">raise</span> <span class="no">StopIteration</span> <span class="k">if</span> <span class="n">i</span> <span class="o">...</span>
<span class="k">end</span>
</code></pre>
<a name="Solution"></a>
<h1 >Solution<a href="#Solution" class="wiki-anchor">¶</a></h1>
<p>What I propose with this patch is making <code>loop</code> yield the iteration count:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="kp">loop</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="c1"># do something with i....</span>
<span class="k">raise</span> <span class="no">StopIteration</span> <span class="k">if</span> <span class="n">i</span> <span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p><code>i</code> starts at 0 and stops at <code>FIXNUM_MAX</code> (there's no <code>Float::Infinity</code> equivalent for integers).</p>
<a name="Alternate-solution"></a>
<h1 >Alternate solution<a href="#Alternate-solution" class="wiki-anchor">¶</a></h1>
<p><code>Integer#times</code> could work if we had an <code><Integer's infinity></code> object, so we would just do <code><Integer's Infinity>.times { |i| ... }</code>.</p>
<p>Also, this is the very first patch I submit to Ruby, I might have done something horrible, feel free to tell me :-)</p> Ruby master - Feature #10489 (Open): Add inherit method for clearer and multiple inheritancehttps://bugs.ruby-lang.org/issues/104892014-11-09T01:57:19Zbrauliobo (Bráulio Bhavamitra)brauliobo@gmail.com
<p>A new and more intuitive syntax:</p>
<pre><code>class B
end
class A
inherit B
end
</code></pre>
<p>Instead of (but keeping this for backwards compatibility):</p>
<pre><code>class B
end
class A < B
end
</code></pre>
<p>Besides, this allows multiple inheritance. Also, <code>inherit</code> could be implemented with just <code>extend</code> plus <code>include</code>?</p> Ruby master - Feature #10481 (Assigned): Add "if" and "unless" clauses to rescue statementshttps://bugs.ruby-lang.org/issues/104812014-11-05T19:20:10Zjavawizard (Alex Boyd)alex@opengroove.org
<p>I'd like to propose a syntax change: allow boolean "if" and "unless" clauses to follow a rescue statement.</p>
<p>Consider the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span>
<span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">else</span>
<span class="k">raise</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>This is a fairly common way of dealing with exceptions where some condition above and beyond the exception's type determines whether the exception should be rescued. It's verbose, though, and it's not obvious at first glance exactly what conditions are being rescued, especially if "...handle error..." is more than a few lines long. I propose that the following be allowed:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>"unless" would, of course, be allowed as well:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">unless</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">2</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>A rescue statement whose boolean condition failed would be treated the same as if the exception being raised didn't match the exception being rescued, and move on to the next rescue statement:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span> <span class="n">code</span> <span class="mi">1</span><span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">2</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span> <span class="n">code</span> <span class="mi">2</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>And finally, catch-all rescue statements would be allowed as well:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">message</span> <span class="o">==</span> <span class="s2">"some error"</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre> Ruby master - Feature #10404 (Open): Allow individual finalizers to be removed with ObjectSpace.u...https://bugs.ruby-lang.org/issues/104042014-10-20T08:14:36Zjavawizard (Alex Boyd)alex@opengroove.org
<p>Pretty self-explanatory: allow removal of individual define_finalizer blocks without removing all of them as undefine_finalizer currently does.</p>
<p>From an API standpoint, this could be done by having define_finalizer return some sort of unique value (maybe an integer, or perhaps the type is unspecified), and this value could then be passed as undefine_finalizer's second argument to remove just that finalizer.</p> Ruby master - Feature #10287 (Open): rename COLON3 to COLON2_HEAD.https://bugs.ruby-lang.org/issues/102872014-09-23T16:15:00Zarimay (yasuhiro arima)
<p>主に parse.y を読んでいて、DOT2 に対する DOT3 はわかるのですが、COLON2 に対する COLON3 はよくない名前だと思いました。<br>
COLON3 の表すものは ::FOO::BAR のようにスコープ指定の先頭を表すものなので、COLON2_HEAD としてパッチを作ってみました。</p> Ruby master - Feature #9816 (Assigned): 文字列内の数字を数値として比較するメソッドhttps://bugs.ruby-lang.org/issues/98162014-05-08T09:37:26Znaruse (Yui NARUSE)naruse@airemix.jp
<p>文字列内の数字を数値として比較するメソッドを追加しませんか</p>
<p>そのような比較は一般的な用途としてはGUIシェルのファイラーが比較に用いており、<br>
Windows では StrCmpLogicalW が、OS X では NSString:compare:options:へのNSNumericSearch定数が提供されています。<br>
<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/bb759947(v=vs.85).aspx" class="external">http://msdn.microsoft.com/en-us/library/windows/desktop/bb759947(v=vs.85).aspx</a><br>
<a href="https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/c/econst/NSNumericSearch" class="external">https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/c/econst/NSNumericSearch</a></p>
<p>上記のような処理自体はさほど難しいものではありませんが、Rubyレベルで実装すると大量のオブジェクトを作ってしまいます。<br>
例えば <code>Gem::Version.new("2.1.10".freeze)<=>Gem::Version.new("2.1.9".freeze)</code> は47個、<br>
<code>"2.1.10".freeze.split('.').map(&:to_i)<=>"2.1.9".freeze.split('.').map(&:to_i)</code> だと16個のオブジェクトを作ります。<br>
<code>"2.1.10".freeze.numericcmp"2.1.9".freeze</code> ならば、もちろんオブジェクトは一つも作りません。</p>
<p>なお、上記の例でも示唆していますが、本メソッドは Ruby のバージョン表記の TEENY が2桁になった場合の比較に用いることができます。</p>
<p>パッチは以下の通りです。<br>
なお、メソッド名は String#numericcmp としています。<br>
(String#casecmpを念頭に置いた)</p>
<pre><code>diff --git a/string.c b/string.c
index c589c80..66f667f 100644
--- a/string.c
+++ b/string.c
@@ -2569,6 +2569,131 @@ rb_str_casecmp(VALUE str1, VALUE str2)
return INT2FIX(-1);
}
+VALUE
+numerical_compare(const char **pp1, const char *p1end, const char **pp2, const char *p2end)
+{
+ const char *s1 = *pp1, *p1, *s2 = *pp2, *p2;
+ ptrdiff_t len1, len2;
+ int r;
+
+ while (s1 < p1end && *s1 == '0') s1++;
+ p1 = s1;
+ while (p1 < p1end && ISDIGIT(*p1)) p1++;
+ len1 = p1 - s1;
+
+ while (s2 < p2end && *s2 == '0') s2++;
+ p2 = s2;
+ while (p2 < p2end && ISDIGIT(*p2)) p2++;
+ len2 = p2 - s2;
+
+ if (len1 != len2) {
+ return INT2FIX(len1 < len2 ? -1 : 1);
+ }
+
+ r = memcmp(s1, s2, len1);
+ if (r) return r < 0 ? INT2FIX(-1) : INT2FIX(1);
+
+ len1 = s1 - *pp1;
+ len2 = s2 - *pp2;
+ if (len1 != len2) {
+ return INT2FIX(len1 < len2 ? -1 : 1);
+ }
+
+ *pp1 = p1;
+ *pp2 = p2;
+ return Qnil;
+}
+
+/*
+ * call-seq:
+ * str.numericcmp(other_str) -> -1, 0, +1 or nil
+ *
+ * Variant of <code>String#<=></code>, which considers digits in strings
+ * are numeric value..
+ *
+ * "a1".numericcmp("a1") #=> 0
+ * "aa".numericcmp("a1") #=> 1
+ * "a1".numericcmp("aa") #=> -1
+ * "a1".numericcmp("a01") #=> -1
+ * "2.1.2".numericcmp("2.1.10") #=> 1
+ */
+
+static VALUE
+rb_str_numericcmp(VALUE str1, VALUE str2)
+{
+ long len;
+ rb_encoding *enc;
+ const char *p1, *p1end, *p2, *p2end;
+
+ StringValue(str2);
+ enc = rb_enc_compatible(str1, str2);
+ if (!enc) {
+ return Qnil;
+ }
+
+ p1 = RSTRING_PTR(str1); p1end = RSTRING_END(str1);
+ p2 = RSTRING_PTR(str2); p2end = RSTRING_END(str2);
+ if (single_byte_optimizable(str1) && single_byte_optimizable(str2)) {
+ while (p1 < p1end && p2 < p2end) {
+ if (ISDIGIT(*p1)) {
+ if (ISDIGIT(*p2)) {
+ VALUE r = numerical_compare(&p1, p1end, &p2, p2end);
+ if (!NIL_P(r)) return r;
+ }
+ else {
+ return INT2FIX(-1);
+ }
+ }
+ else if (ISDIGIT(*p2)) {
+ return INT2FIX(1);
+ }
+ if (*p1 != *p2) return INT2FIX(*p1 < *p2 ? -1 : 1);
+ p1++;
+ p2++;
+ }
+ }
+ else {
+ while (p1 < p1end && p2 < p2end) {
+ int l1, c1 = rb_enc_ascget(p1, p1end, &l1, enc);
+ int l2, c2 = rb_enc_ascget(p2, p2end, &l2, enc);
+
+ if (0 <= c1 && 0 <= c2) {
+ if (ISDIGIT(*p1)) {
+ if (ISDIGIT(*p2)) {
+ VALUE r = numerical_compare(&p1, p1end, &p2, p2end);
+ if (!NIL_P(r)) return r;
+ }
+ else {
+ return INT2FIX(-1);
+ }
+ }
+ else if (ISDIGIT(*p2)) {
+ return INT2FIX(1);
+ }
+ if (*p1 != *p2) return INT2FIX(*p1 < *p2 ? -1 : 1);
+ p1++;
+ p2++;
+ }
+ else {
+ int r;
+ l1 = rb_enc_mbclen(p1, p1end, enc);
+ l2 = rb_enc_mbclen(p2, p2end, enc);
+ len = l1 < l2 ? l1 : l2;
+ r = memcmp(p1, p2, len);
+ if (r != 0)
+ return INT2FIX(r < 0 ? -1 : 1);
+ if (l1 != l2)
+ return INT2FIX(l1 < l2 ? -1 : 1);
+ }
+ p1 += l1;
+ p2 += l2;
+ }
+ }
+ if (RSTRING_LEN(str1) == RSTRING_LEN(str2)) return INT2FIX(0);
+ if (RSTRING_LEN(str1) > RSTRING_LEN(str2)) return INT2FIX(1);
+ return INT2FIX(-1);
+}
+
static long
rb_str_index(VALUE str, VALUE sub, long offset)
{
@@ -8721,6 +8846,7 @@ Init_String(void)
rb_define_method(rb_cString, "eql?", rb_str_eql, 1);
rb_define_method(rb_cString, "hash", rb_str_hash_m, 0);
rb_define_method(rb_cString, "casecmp", rb_str_casecmp, 1);
+ rb_define_method(rb_cString, "numericcmp", rb_str_numericcmp, 1);
rb_define_method(rb_cString, "+", rb_str_plus, 1);
rb_define_method(rb_cString, "*", rb_str_times, 1);
rb_define_method(rb_cString, "%", rb_str_format_m, 1);
diff --git a/test/ruby/test_string.rb b/test/ruby/test_string.rb
index 8366424..f9c788b 100644
--- a/test/ruby/test_string.rb
+++ b/test/ruby/test_string.rb
@@ -2104,6 +2104,29 @@ class TestString < Test::Unit::TestCase
assert_equal(1, "\u3042B".casecmp("\u3042a"))
end
+ def test_numericcmp
+ assert_equal(-1, "2.1.0".numericcmp("2.1.1"))
+ assert_equal(-1, "2.1.9".numericcmp("2.1.10"))
+ assert_equal( 0, "a1".numericcmp("a1"))
+ assert_equal( 1, "aa".numericcmp("a1"))
+ assert_equal(-1, "a1".numericcmp("aa"))
+ assert_equal(-1, "a1".numericcmp("a01"))
+ assert_equal(-1, "a0001".numericcmp("a00001"))
+ assert_equal( 0, "a1a".numericcmp("a1a"))
+ assert_equal( 1, "a1b".numericcmp("a1a"))
+ assert_equal(-1, "a9a".numericcmp("a10a"))
+ assert_equal( 1, "b".numericcmp("a"))
+ assert_equal( 0, "\u30421".numericcmp("\u30421"))
+ assert_equal( 1, "\u3042\u3042".numericcmp("\u30421"))
+ assert_equal(-1, "\u30421".numericcmp("\u3042\u3042"))
+ assert_equal(-1, "\u30421".numericcmp("\u304201"))
+ assert_equal(-1, "\u30420001".numericcmp("\u304200001"))
+ assert_equal( 0, "\u30421\u3042".numericcmp("\u30421\u3042"))
+ assert_equal( 1, "\u30421\u3044".numericcmp("\u30421\u3042"))
+ assert_equal(-1, "\u30429\u3042".numericcmp("\u304210\u3042"))
+ assert_equal( 1, "\u3044".numericcmp("\u3042"))
+ end
+
def test_upcase2
assert_equal("\u3042AB", "\u3042aB".upcase)
end
</code></pre> Ruby master - Feature #9768 (Assigned): Method that is visible only within a certain module/classhttps://bugs.ruby-lang.org/issues/97682014-04-22T09:57:35Zsawa (Tsuyoshi Sawada)
<p>Some frameworks/libraries monkeypatch their own methods on Ruby core classes like <code>String</code>, <code>Hash</code>, <code>Array</code>, etc., and that is often causing problems/concerns of name conflict.</p>
<p>Seeing that these custom methods are used only in the context of a certain module/class, I request for a way to define a method (<code>foo</code>) on a module/class (<code>A</code>) so that it will be visible only from within a specified module/class (<code>B</code>) or its descendants. The following illustrates this situation:</p>
<pre><code>A.new.foo # => undefined
class B
A.new.foo # => defined
def bar
A.new.foo # => defined
end
def self.baz
A.new.foo # => defined
end
end
class C < B
A.new.foo # => defined
def bar
A.new.foo # => defined
end
def self.baz
A.new.foo # => defined
end
end
</code></pre>
<p>I do not have a certain syntax for this in mind, but I think it can be made much simpler, compared to the complicated syntax of refinement.</p>
<p>This is reminiscent of refinement, but they are pretty much different.</p>
<p>Refinement's purpose is to let certain methods be accessible from only a certain file. A typical use case would be a library developer defining their methods to be used from within the library and making such methods inaccessible from the end user.</p>
<p>On the other hand, the idea I am proposing here is for making method accessible from any file, but only within a certain module/class. A typical use case would be defining a method to be used by an end user, but only from within a context of certain module/class.</p> Ruby master - Feature #9704 (Open): Refinements as files instead of moduleshttps://bugs.ruby-lang.org/issues/97042014-04-04T20:41:06Ztrans (Thomas Sawyer)
<p>If refinements are to remain file-scoped, then it would be more convenient if <code>using</code> worked at the file level, akin to <code>require</code>, rather than behave like a module <code>include</code>. For instance, instead of:</p>
<pre><code># foo.rb
module Foo
refine String do
def some_method
...
end
end
end
</code></pre>
<pre><code>require 'foo'
using Foo
</code></pre>
<p>We could do:</p>
<pre><code># foo.rb
class String
def some_method
...
end
end
</code></pre>
<pre><code>using 'foo'
</code></pre>
<p>This would make <code>require</code> and <code>using</code>, in a certain sense, <em>polymorphic</em> --if we <code>require</code> it will extend the classes directly, but if <code>using</code> then they will be refined instead.</p> Ruby master - Feature #9614 (Open): ordering of non-Hash items which use st_ internallyhttps://bugs.ruby-lang.org/issues/96142014-03-09T02:25:28Znormalperson (Eric Wong)normalperson@yhbt.net
<p>Hi matz, I would like your permission to remove the order preservation from<br>
any or all of the following currently implemented using <code>st_table</code>:</p>
<ul>
<li>method tables</li>
<li>global symbols (<code>Symbol.all_symbols</code>)</li>
<li>constant tables</li>
<li>instance variable tables</li>
<li>
<code>global_variables</code> method</li>
<li><code>Thread#keys</code></li>
<li>anything besides the <code>Hash</code> class</li>
</ul>
<p>I am currently working on a patch series to reduce internal memory usage,<br>
so far I have only converted three pieces:</p>
<ol>
<li>method tables (~200K reduction)</li>
<li>symbol table (<code>global_symbols.</code>{<code>id_str</code>,<code>sym_id</code>}) (~200K)</li>
<li>
<code>frozen_strings</code> (~100K)</li>
</ol>
<p>n.b. <code>frozen_strings</code> ordering is never exposed to users, so I expect<br>
it to be OK.</p>
<p>Memory reduction is just based on "<code>ruby -e exit</code>" (which loads RubyGems);<br>
bigger programs with more methods/symbols will save more memory.</p>
<p>Work-in-progress patches attached (0002 describes implementation details)</p> Ruby master - Feature #9123 (Open): Make Numeric#nonzero? behavior consistent with Numeric#zero?https://bugs.ruby-lang.org/issues/91232013-11-19T03:12:47Zsferik (Erik Michaels-Ober)sferik@gmail.com
<p>Numeric#zero? returns true or false, while Numeric#nonzero? returns self or nil.</p>
<p>I've written a patch that fixes this inconsistency and adds a Numeric#nonzero (non-predicate) method that returns self or nil for chaining comparisons. I'd like for this to be included in Ruby 2.1.0.</p>
<p><a href="https://github.com/ruby/ruby/pull/452.patch" class="external">https://github.com/ruby/ruby/pull/452.patch</a></p> Ruby master - Feature #9070 (Open): Introduce `---` as synonym of `end` keywordhttps://bugs.ruby-lang.org/issues/90702013-11-01T23:17:58Zalexeymuranov (Alexey Muranov)
<p>=begin<br>
This is just an idea: introduce "(({---}))" as synonym of "(({end}))" keyword.</p>
<p>It is a bit easier to type and to read, and makes whitespace insensitive language look as if it follows off-side rule. Compare:</p>
<h2>class Person<br>
attr_reader :name, :age<br>
def initialize(name, age)<br>
@name, @age = name, age<br>
---<br>
def <=>(person) # the comparison operator for sorting<br>
age <=> person.age<br>
---<br>
def to_s<br>
"#{name} (#{age})"<br>
---</h2>
<p>class Person<br>
attr_reader :name, :age<br>
def initialize(name, age)<br>
@name, @age = name, age<br>
end<br>
def <=>(person) # the comparison operator for sorting<br>
age <=> person.age<br>
end<br>
def to_s<br>
"#{name} (#{age})"<br>
end<br>
end</p>
<p>=end</p> Ruby master - Feature #9043 (Open): Add String#f method as shortcut for #freezehttps://bugs.ruby-lang.org/issues/90432013-10-22T21:16:59Zheadius (Charles Nutter)headius@headius.com
<p>We have String#b to create a binary-encoded String, and we have the "f" suffix (going away, hopefully) and the "literal".freeze optimization (<a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Use String#freeze and compiler tricks to replace "str"f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a>). I think it would be reasonable to add String#f as a shorter method for producing a frozen string.</p>
<p>If String#f is added the "literal".freeze optimization could be dropped in favor of "literal".f. This would provide something very close to the original "literal"f syntax but in a backward-compatibility-friendly way (class String; alias f freeze; end).</p> Ruby master - Feature #8839 (Assigned): Class and module should return the class or module that w...https://bugs.ruby-lang.org/issues/88392013-08-31T02:57:19Zheadius (Charles Nutter)headius@headius.com
<p>With the change for <a href="https://bugs.ruby-lang.org/issues/3753" class="external">https://bugs.ruby-lang.org/issues/3753</a>, "def" forms now return the symbolic name of the method defined. Because class and module bodies just return the last expression in their bodies, this means they will now usually end up returning a symbol for the last method defined. This does not seem useful or correct.</p>
<p>I think class and module should return a reference to the class or module just opened. This would make the return value useful and consistent.</p> Ruby master - Feature #8804 (Open): ONCE syntaxhttps://bugs.ruby-lang.org/issues/88042013-08-20T11:45:48Zko1 (Koichi Sasada)
<p>How about to introduce ONCE{...} syntax which do block only once and return the first value?</p>
<ul>
<li>It is similar of BEGIN{} and END{}.</li>
<li>General syntax of /reg/o.</li>
</ul>
<a name="simulation-code"></a>
<h2 >simulation code<a href="#simulation-code" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">ONCE_CACHE</span> <span class="o">=</span> <span class="p">{}</span>
<span class="no">ONCE_MUTEX</span> <span class="o">=</span> <span class="no">Mutex</span><span class="p">.</span><span class="nf">new</span>
<span class="k">def</span> <span class="nf">ONCE</span><span class="p">(</span><span class="o">&</span><span class="n">b</span><span class="p">)</span>
<span class="k">raise</span> <span class="k">unless</span> <span class="nb">block_given?</span>
<span class="no">ONCE_MUTEX</span><span class="p">.</span><span class="nf">synchronize</span><span class="p">{</span>
<span class="n">key</span> <span class="o">=</span> <span class="nb">caller</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="n">value</span> <span class="o">=</span> <span class="no">ONCE_CACHE</span><span class="p">[</span><span class="n">key</span><span class="p">]</span>
<span class="n">value</span>
<span class="k">else</span>
<span class="no">ONCE_CACHE</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="k">yield</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="k">end</span>
<span class="mi">3</span><span class="p">.</span><span class="nf">times</span><span class="p">{</span><span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="nb">p</span> <span class="no">ONCE</span><span class="p">{</span>
<span class="n">i</span> <span class="c1">#=> every time 0</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<h2></h2>
<a name="Note-that-this-code-doesnt-work-if-two-or-more-ONCE-are-available-in-one-line"></a>
<h2 >Note that this code doesn't work if two or more ONCE{} are available in one line.<a href="#Note-that-this-code-doesnt-work-if-two-or-more-ONCE-are-available-in-one-line" class="wiki-anchor">¶</a></h2> Ruby master - Feature #8663 (Open): Officialy alias ArgumentError to ArgErrorhttps://bugs.ruby-lang.org/issues/86632013-07-23T00:07:56ZAnonymous
<p>When not using custom made exceptions, I find myself using TypeError, NameError and ArgumentError the most. ArgumentError is the longest and I would like to suggest to alias it officially as ArgError.</p> Ruby master - Feature #8478 (Open): The hash returned by Enumerable#group_by should have an empty...https://bugs.ruby-lang.org/issues/84782013-06-03T04:37:46Zphiggins (Pete Higgins)pete@peterhiggins.org
<p>Without this patch, nil checks might need to be done on the return value of Enumerable#group_by:</p>
<p>$ cat test_group_by.rb<br>
a = [1, 2, 3, "a", "b"]<br>
g = a.group_by {|o| o.class }</p>
<p>puts "Fixnums: #{g[Fixnum].size}"<br>
puts "Strings: #{g[String].size}"<br>
puts "Arrays: #{g[Array].size}"</p>
<p>$ ruby test_group_by.rb<br>
Fixnums: 3<br>
Strings: 2<br>
test_group_by.rb:6:in <code><main>': undefined method </code>size' for nil:NilClass (NoMethodError)</p>
<p>This patch adds a default value of an empty array to the hash returned by Enumerable#group_by, so the script above will work:</p>
<p>$ ./ruby -I.:lib test_group_by.rb<br>
Fixnums: 3<br>
Strings: 2<br>
Arrays: 0</p> Ruby master - Feature #8232 (Open): Rudiments of abstract algebra in Rubyhttps://bugs.ruby-lang.org/issues/82322013-04-07T18:25:12ZAnonymous
<p>I have recently been struggling with Matrix class to make it accept physical magnitudes for matrix multiplication, and at that opportunity (<a href="http://bugs.ruby-lang.org/issues/8223" class="external">http://bugs.ruby-lang.org/issues/8223</a>), I noticed that rings and fields in Ruby do not know their additive identity. Eg. there is no method Float#zero or Rational#zero... I therefore propose that:</p>
<ol>
<li>every ring has #additive_identity, alias #zero method defined.</li>
<li>every ring has other methods defined, as required for rings in abstract algebra. An example (perhaps a stupid example) might be:</li>
</ol>
<p>class << Integer<br>
def additive_identity; 0 end<br>
alias zero additive_identity<br>
def add( other ); self + other end<br>
def additive_inverse; -self end<br>
def multiply( other ); self * other end<br>
def multiplicative_identity; 1 end<br>
end</p>
<ol start="3">
<li>That every field in Ruby has, in addition to the above methods, a method #multiplicative_inverse defined, as in:</li>
</ol>
<p>class << Float<br>
def additive_identity; 0.0 end<br>
alias zero additive_identity<br>
def add( other ); self + other end<br>
def additive_inverse; -self end<br>
def multiply( other ); self * other end<br>
def multiplicative_identity; 1.0 end<br>
alias one multiplicative_identity<br>
def multiplicative_inverse; 1.0 / self end<br>
end</p>
<p>I am no pro mathematician, and abstract algebra first sounded to me like a kind of thing that should be treated in some specialized libraries for math nerds, but looking how Twitter pays people to write abstract algebra in Scala</p>
<p><a href="https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/Monoid.scala" class="external">https://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/Monoid.scala</a></p>
<p>and reading posts like this one about it:</p>
<p><a href="http://stackoverflow.com/questions/14790588/what-is-twitters-interest-in-abstract-algebra" class="external">http://stackoverflow.com/questions/14790588/what-is-twitters-interest-in-abstract-algebra</a></p>
<p>, where especially noteworthy comment is that by Randall Schulz of box.com, fourth from the top.</p>
<p>If we actually require Ruby rings and fields to have the basic properties of rings and fields (just like Enumerable classes are required to have #each method), it would be possible to implement structured objects such as Matrices over them, and instead of intuitively using numeric literals such as 0 and 1, the matrix or another structured object would ask rings / fields, which their elements come from, what their #additive_identity (#zero), #multiplicative_identity (#one) is. And at the same time, I would like to express my wish that Matrix be made a standard part of Ruby, that does not need to be loaded by require.</p> Ruby master - Feature #8229 (Open): extend Hash.include?https://bugs.ruby-lang.org/issues/82292013-04-07T08:14:09Zeike.rb (Eike Dierks)eike@inter.net
<p>I'd like to suggest to extend the Hash.include? method.</p>
<p>Currently Hash.include? can only be used to ask for a key,<br>
I believe it should be extended to ask for a (key value) pair.</p>
<p>I believe this extension can be done without breaking prior api.</p>
<p>I suggest to extend the signature of Hash.include?<br>
to Hash.include?(key, value)</p>
<p>That message should return true,<br>
if the receiving object does have an object at key which is equal to value.</p>
<p>It would be a simple replacement for:<br>
h.include?(key) && h[key] == value</p>
<p>But I do not want to stop there.<br>
I'm heading for h.include_all?(other_hash)<br>
and h.include_any?(other_hash)</p>
<p>and it would be valuable to have h.intersect(other_hash) etc</p>
<p>I believe these to be useful primitives when working with hashes.</p>
<p>I'd like to have the api of the Set class available for the Hash class as well,<br>
but there working on key/value matching.</p>
<p>Obviously any change to such the substantial class as the Hash class<br>
needs a lot of thought for compatibility.</p>
<p>But I believe this can be done without breaking any prior code,<br>
and it could add a lot of new out of the box functionality.</p>
<p>This probably needs some more thought.<br>
We might come up with some dsl like thing like<br>
h.includes.any? or h.includes.all? or h.includes.none?<br>
to be used cross all collection classes.</p>
<p>Someone must be in charge for the Hash class,<br>
my 2p</p> Ruby master - Feature #8061 (Open): 重複するキーワードをエラーにするhttps://bugs.ruby-lang.org/issues/80612013-03-10T09:53:22Ztadf (tadayoshi funaba)
<p>重複するキーワードをエラーにする。</p>
<p>def m(a:1, b:2)<br>
p [a, b]<br>
end</p>
<p>m(a:8, a:9)</p> Ruby master - Feature #7914 (Open): Case for local class methodshttps://bugs.ruby-lang.org/issues/79142013-02-23T00:13:20Ztrans (Thomas Sawyer)
<p>=begin<br>
Here is a use case for local class methods.</p>
<p>Say we wish to give certain classes and all subclasses a special name.</p>
<p>class X<br>
def self.special_name<br>
"special:#{name}"<br>
end<br>
end<br>
class Y < X; end<br>
class Z < Y; end</p>
<p>Z.special_name #=> "special:Z"</p>
<p>But what if Y has a unique special name?</p>
<p>class Y < X<br>
def special_name<br>
'unique:Y'<br>
end<br>
end</p>
<p>Problem that arises:</p>
<pre><code>Z.special_name #=> "unique:Y" # wrong!
</code></pre>
<p>Currently, to solve this would require creating an additional method, e.g. <code>unique_name</code> and redefine <code>special_name</code> to first look for unique_name then fallback to default special name if non-found. It works, but adds additional complexity to API.</p>
<p>Nicer solution would be local class methods.</p>
<pre><code>class Y < X
def special_name
'unique:Y'
end
local :special_name
end
Y.special_name #=> "unique:Y"
Z.special_name #=> "special:Z"
</code></pre>
<p>The idea being that local class methods are skipped in super/lookup chain.</p>
<p>This idea is not without precedence. Module class methods can be thought of as being local. So this idea has other side of the notion, that modules could have class methods that are not skipped over in the super/lookup chain. In that case we would need a term that means opposite of local, so I'll use <code>nonlocal</code>:</p>
<pre><code>module M
def self.q; "q"; end
nonlocal :q
end
class X
include M
end
X.q #=> "q"
</code></pre>
<p>=end</p> Ruby master - Feature #7883 (Open): Add Regex#to_prochttps://bugs.ruby-lang.org/issues/78832013-02-19T16:58:30Zrklemme (Robert Klemme)shortcutter@googlemail.com
<p>Just a small addition to the standard library:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Regexp</span>
<span class="k">def</span> <span class="nf">to_proc</span><span class="p">;</span> <span class="nb">lambda</span> <span class="p">{</span><span class="o">|</span><span class="n">s</span><span class="o">|</span> <span class="nb">self</span> <span class="o">=~</span> <span class="n">s</span><span class="p">}</span> <span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>With that one can use a <code>Regexp</code> everywhere a <code>Proc</code> is used as filtering criteria saving a bit of typing. While we have <code>Enumerable#grep</code> already there may be other cases where you want to do something like</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">00</span><span class="mi">8</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="sx">%w{foo bar baz}</span><span class="p">.</span><span class="nf">select</span> <span class="o">&</span><span class="sr">/\Ab/</span>
<span class="o">=></span> <span class="p">[</span><span class="s2">"bar"</span><span class="p">,</span> <span class="s2">"baz"</span><span class="p">]</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">00</span><span class="mi">9</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="sx">%w{foo bar baz}</span><span class="p">.</span><span class="nf">reject</span> <span class="o">&</span><span class="sr">/\Ab/</span>
<span class="o">=></span> <span class="p">[</span><span class="s2">"foo"</span><span class="p">]</span>
<span class="n">irb</span><span class="p">(</span><span class="n">main</span><span class="p">):</span><span class="mo">010</span><span class="p">:</span><span class="mi">0</span><span class="o">></span> <span class="sx">%w{foo bar baz}</span><span class="p">.</span><span class="nf">find</span> <span class="o">&</span><span class="sr">/\Ab/</span>
<span class="o">=></span> <span class="s2">"bar"</span>
</code></pre>
<p>Note: line 9 and 10 are not possible with <code>Enumerable#grep</code> AFAIK.</p>
<p>I see low risk of breaking something.</p> Ruby master - Feature #7876 (Open): Add method for accessing Class from within Singleton Classhttps://bugs.ruby-lang.org/issues/78762013-02-18T19:59:29Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
I'm quite surprised I haven't run into this sooner, but I seem to have just discovered that there's no means by which you can access the outer Class object once inside the context of the Singleton Class. Take the following example; how would I get a reference to (({Test})) from within the singleton?</p>
<p>class Test<br>
class << self<br>
# How do I get a reference to Test from here?<br>
end<br>
end</p>
<p>I assume the answer is that there is no reliable way, hence the reason for this request. Could we add a method to the singleton class that allows access to the "outer" class, e.g.</p>
<p>class Test<br>
class << self<br>
self.outerclass<br>
end<br>
end</p>
<p>Thoughts?<br>
=end</p> Ruby master - Feature #7848 (Open): Restore default state for core ruby objectshttps://bugs.ruby-lang.org/issues/78482013-02-14T04:41:33Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hi.</p>
<p>Consider:</p>
<p>class String<br>
def lala<br>
puts 'Running lala() from class String.'<br>
end<br>
end</p>
<p>This is possible.</p>
<p>My question is - is there a reason why we can not restore<br>
to the default ruby state again?</p>
<p>For instance, if I would do:</p>
<p>String.restore</p>
<p>I could undo all modifications to String, save what was used<br>
in String class on startup/initialize.</p>
<p>The reason I would like to have something like this is so<br>
that I could safely undo all "monkey" patches again, if needed,<br>
for a given project.</p> Ruby master - Feature #7795 (Open): Symbol.defined? and/or to_existing_symbolhttps://bugs.ruby-lang.org/issues/77952013-02-07T14:08:11ZStudent (Nathan Zook)blogger@pierian-spring.net
<p>I'm pulling this out from deep in the discussions of issue <a href="http://bugs.ruby-lang.org/issues/7791" class="external">http://bugs.ruby-lang.org/issues/7791</a>, Let Symbols be Garbage Collected.</p>
<p>The problem is that the extreme utility of symbols makes them enticed to use, which results in a DOS vulnerability. My proposal is to add either of a pair of methods that would make it easy to defend against a DOS along these lines.</p>
<p>#1) Symbol.defined?</p>
<p>In existing code, it would might like this:<br>
class Symbol<br>
def self.defined?(string)<br>
all_symbols.any?{|sym| sym.to_s == string}<br>
end<br>
end</p>
<p>#2) to_existing_sym. This would be defined in the same places as to_sym, but would through an argument error if the symbol did not already exist.</p> Ruby master - Feature #7748 (Open): Contextual sendhttps://bugs.ruby-lang.org/issues/77482013-01-28T16:11:40Ztrans (Thomas Sawyer)
<p>=begin<br>
If I write a method that uses #send vs. #public_send, I am making an assumption about how that method is invoked. For example, take the simplest form of such a method:</p>
<p>class String<br>
def send_out(op, *a, &b)<br>
send(op, *a, &b)<br>
end<br>
end</p>
<p>This code has a bug in it, in the sense that it can be used to call private string methods. The solution is to use #public_send. In most cases that will be fine. But if anyone tries to reuse the method while extending String themselves, e.g.</p>
<p>class String<br>
def send_out(op, *a, &b)<br>
public_send(op, *a, &b)<br>
end</p>
<pre><code>def some_public_method
send_out(:some_private_method)
end
private
def some_private_method
end
</code></pre>
<p>end</p>
<p>Then it will be a problem b/c it cannot be used on a private supporting method.</p>
<p>So it seems like there should be something like a ((<em>contextual send</em>)) which invokes a send with the same visibility as the parent method is invoked. e.g.</p>
<p>class String<br>
def send_out(op, *a, &b)<br>
contextual_send(op, *a, &b)<br>
end<br>
end</p>
<p>And then all cases will work as expected.<br>
=end</p> Ruby master - Feature #7704 (Open): Add a list of enabled (experimental) language features.https://bugs.ruby-lang.org/issues/77042013-01-16T10:54:37Zmpapis (Michal Papis)mpapis@gmail.com
<p>With multiple Ruby implementations and "experimental" features like "refinements" it would be nice to have an array or hash including list of enabled language features so developers could check it instead of auto-discovering code with some hacks.</p>
<p>Additionally a new keyword like <code>require_features :refinements, ...</code> could be introduced to allow easy validation via either exception or return status.</p> Ruby master - Feature #7702 (Open): Remove Proc#bindinghttps://bugs.ruby-lang.org/issues/77022013-01-16T09:09:14Zjballanc (Joshua Ballanco)jballanc@gmail.com
<p>=begin<br>
As discussed in the most recent Ruby implementer's meeting and elsewhere over the years, being able to get a handle to the binding of any block/proc has a number of problems:</p>
<ul>
<li>Code execution after passing a block/proc in unpredictable, as the binding of said proc can be used to redefine any local, instance variable, method, class, module, etc.</li>
<li>Potentially sensitive data can leak out of the scope of a method via a proc binding</li>
<li>Large object graphs may need to be retained for the lifetime of a proc, since any identifier in scope at the time of proc creation must remain live in the event that the binding of the proc is used to evaluate code</li>
</ul>
<p>Additionally, removal of Proc#binding would enable a number of very useful optimizations and performance improvements.<br>
=end</p> Ruby master - Feature #7657 (Open): Array#& doesn't accept Enumerableshttps://bugs.ruby-lang.org/issues/76572013-01-06T09:00:39ZNevir (Ian MacLeod)ian@nevir.net
<p>This seems similar to <a href="http://bugs.ruby-lang.org/issues/6923" class="external">http://bugs.ruby-lang.org/issues/6923</a></p>
<p>Example:</p>
<pre><code>irb(main):001:0> class Thing
irb(main):002:1> include Enumerable
irb(main):003:1> def each(*args, &block)
irb(main):004:2> [1,2,3,4,5].each(*args, &block)
irb(main):005:2> end
irb(main):006:1> end
=> nil
irb(main):007:0> Array(Thing.new) & [1,3,5]
=> [1, 3, 5]
irb(main):008:0> [1,3,5] & Thing.new
TypeError: can't convert Thing into Array
irb(main):009:0> Thing.class_eval do
irb(main):010:1* alias_method :to_ary, :to_a
irb(main):011:1> end
=> Thing
irb(main):012:0> [1,3,5] & Thing.new
=> [1, 3, 5]
</code></pre>
<p>Would it make sense for Enumerable to implement to_ary as well? Or is this purely a bug in Array#&?</p> Ruby master - Feature #7654 (Open): Add optional code block to IO::readlineshttps://bugs.ruby-lang.org/issues/76542013-01-04T22:15:05Zshock_one (Володимир Шацький)shockone89@gmail.com
<p>Of course, we always can write something like<br>
File.readlines('/home/shock_one/test.rb').map{ |line| line.upcase }<br>
but this way we create unneeded intermediate array which can be pretty big.<br>
There is also a method IO::foreach, but it doesn't collect return values.<br>
Besides it seems pretty logical and natural to have a block in this method.</p> Ruby master - Feature #7614 (Open): alias_accessorhttps://bugs.ruby-lang.org/issues/76142012-12-24T11:19:06Ztrans (Thomas Sawyer)
<p>=begin<br>
Prior issue reminded me that I've been meaning to ask for this for a while, as I use is fairly often.</p>
<p>In pure Ruby the definition is essentially:</p>
<pre><code>def alias_accessor(name, origin)
alias_method "#{name}=", "#{origin}="
alias_method name, origin
end
</code></pre>
<p>Albeit pursuit to prior mentioned issue, I'd define it more like:</p>
<pre><code>def alias_accessor(name, origin)
writer_name = name.to_s.chomp('?')
alias_method "#{writer_name}=", "#{origin}="
alias_method name, origin
end
</code></pre>
<p>=end</p> Ruby master - Feature #7611 (Open): Focal method for all loads/requireshttps://bugs.ruby-lang.org/issues/76112012-12-23T23:50:40Ztrans (Thomas Sawyer)
<p>=begin<br>
Presently Ruby has seven methods for importing code. These are:</p>
<ul>
<li>(({Kernel#load}))</li>
<li>(({Kernel#require}))</li>
<li>(({Kernel#relative_require}))</li>
<li>(({Kernel.load}))</li>
<li>(({Kernel.require}))</li>
<li>(({Kernel.relative_require}))</li>
<li>(({Kernel#autoload}))</li>
</ul>
<p>Even though the Kernel module methods do the same thing as the instance methods, all of these act independently. If you need to tap into or override code loading in general it means doing so for each and every one.</p>
<p>Would it not be much more elegant if they all called upon one focal method? Lacking another name for this example, lets call it (({#open_eval()})). The method would take a path argument and options for (({feature})), (({relative})) and (({wrap})), where if (({feature})) is true then it is a "require", otherwise it is a "load".</p>
<p>def open_eval(path, feature: false, relative: false, wrap: nil)<br>
...<br>
end</p>
<p>All the other seven methods listed above would route to this one method. So it would then be possible to monitor or override this behavior, e.g. like RubyGems does, via a single interface.</p>
<p>Note, even if this feature request is not accepted, I would like to get some opinion on it, b/c I am currently working on a project where I have to do this (specifically I am in need of require/load callbacks). For the purpose I have created another reusable gem for it and I want to get an idea of what would be considered appropriate API for it.<br>
=end</p> Ruby master - Feature #7604 (Open): Make === comparison operator ability to delegate comparison t...https://bugs.ruby-lang.org/issues/76042012-12-22T21:04:06Zprijutme4ty (Ilya Vorontsov)prijutme4ty@gmail.com
<p>=begin<br>
I propose to expand default behaviour of === operator in the following way:<br>
Objects have additional instance method Object#reverse_comparison?(other) which is false by default in all basic classes.<br>
Each class that overrides Object#===(other) should check whether reverse_comparison? is true or false<br>
If it is false, behavior is not changed at all.<br>
If it is true, comparison is delegated to === method of an argument with self as an argument.</p>
<p>This technique can help in constructing RSpec-style matchers for case statement. Example:</p>
<a name="usual-method-call"></a>
<h1 >usual method call<a href="#usual-method-call" class="wiki-anchor">¶</a></h1>
<p>arr = %w[cat dog rat bat]<br>
puts arr.end_with?(%w[dog bat]) # ==> false<br>
puts arr.end_with?(%w[rat bat]) # ==> true<br>
puts arr.end_with?(%w[bat]) # ==> true</p>
<a name="predicate-style-case"></a>
<h1 >predicate-style case<a href="#predicate-style-case" class="wiki-anchor">¶</a></h1>
<p>case %w[cat dog rat bat].end_with?<br>
when %w[dog bat]<br>
puts '..., dog, bat'<br>
when %w[rat bat]<br>
puts '..., rat, bat'<br>
when %w[bat]<br>
puts '..., bat'<br>
else<br>
puts 'smth else'<br>
end</p>
<a name="gt-rat-bat"></a>
<h1 >==> ..., rat, bat<a href="#gt-rat-bat" class="wiki-anchor">¶</a></h1>
<p>Code needed to run this is not very complex:<br>
class Object<br>
def reverse_comparison?(other)<br>
false<br>
end<br>
alias_method :'old===', :'==='<br>
def ===(other)<br>
(other.reverse_comparison?(self) ? (other.send 'old===',self) : (self.send 'old===',other))<br>
end<br>
end</p>
<p>class Predicate<br>
def initialize(&block)<br>
@block = block<br>
end<br>
def reverse_comparison?(other)<br>
true<br>
end<br>
def ===(*args)<br>
@block.call(*args)<br>
end<br>
end</p>
<p>class Array<br>
alias_method :'old===', :'==='<br>
def ===(other)<br>
other.reverse_comparison?(self) ? (other.send('===',self)) : (self.send('old===',other))<br>
end</p>
<pre><code>def end_with?(expected_elements = nil)
return last(expected_elements.size) == expected_elements if expected_elements
Predicate.new{|suffix| last(suffix.size) == suffix }
end
</code></pre>
<p>end</p>
<p>This technique looks powerful and beautiful for me. One detail is that obj#reverse_comparison? can distinguish different types of arguments and returns true only for certain types of given object. Also this can be used to prevent double-mirroring (as shown below)</p>
<p>The problem is that many base classes already defined custom === operator, so each of those classes (Fixnum, Float, String, Regexp, Range etc) should be redefined in such a way to make a solution full-fledged.<br>
Another problem is case that both objects defined reverse_comparison? to return true. In my solution Predicate#=== just ignores result of revese_comparison? which is not consistent.<br>
Another possible way is to raise errors on double mirroring:<br>
def reverse_comparison?(other)<br>
raise 'double mirroring' if @__mirroring_started<br>
@__mirroring_started = true<br>
return true unless other.reverse_comparison?(self)<br>
false<br>
ensure<br>
remove_instance_variable :@__mirroring_started<br>
end</p>
<p>My proposal is to add reverse_comparison? method and change base classes operator === to use its result as shown above. May be it's worth also to make a class analogous to Predicate in stdlib.<br>
=end</p> Ruby master - Feature #7548 (Open): Load and Require Callbackshttps://bugs.ruby-lang.org/issues/75482012-12-12T13:15:48Ztrans (Thomas Sawyer)
<p>=begin<br>
Should #load and #require have callbacks? e.g.</p>
<p>def required(path)<br>
...<br>
end</p>
<p>def loaded(path, wrap)<br>
...<br>
end</p>
<p>On occasion I have wanted to do load monitoring to track down a bug. This would have made it easier.</p>
<p>Are there any other good use cases?<br>
=end</p> Ruby master - Feature #7546 (Open): Change behavior of `Array#slice` for an argument of `Range` c...https://bugs.ruby-lang.org/issues/75462012-12-12T01:23:22Zalexeymuranov (Alexey Muranov)
<p>=begin<br>
This is a concrete proposal to "fix" <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Inconsistent Array.slice() (Rejected)" href="https://bugs.ruby-lang.org/issues/4541">#4541</a>.</p>
<p>It is also related to <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Make Range act as a "lazy ordered set" (Open)" href="https://bugs.ruby-lang.org/issues/7545">#7545</a>.<br>
For this proposal to make good sense, i think it would be nice if <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Make Range act as a "lazy ordered set" (Open)" href="https://bugs.ruby-lang.org/issues/7545">#7545</a> was at least partially accepted.</p>
<p>=== Main proposal</p>
<p>I propose (({Array#slice})) with (({Range})) type argument to work as follows:</p>
<p>a = ['0', '1', '2', '3']<br>
a[1..2] # => ['1', '2']<br>
a[-2..-1] # => ['2', '3']<br>
a[2..1] # => ['2', '1']<br>
a[-1..-2] # => ['3', '2']<br>
a[-1..1] # => ['3', '0', '1']<br>
a[1..-1] # => ['1', '0', '3']<br>
a[1..1] # => ['1']<br>
a[1...1] # => []<br>
a[4..4] # => [nil]<br>
a[4...4] # => []<br>
a[9..9] # => [nil]<br>
a[9...9] # => []<br>
a[1..5] # => ['1', '2', '3', nil, nil]</p>
<p>=== Secondary proposal: consider adding new instance methods to (({Array})) to compensate the changed behavior of (({Array#slice}))</p>
<p>If this proposal is accepted, the code "(({a[1..-2]}))" for an array (({a})) will not work as before.<br>
This can be compensated by adding new instance methods to (({Array})).<br>
For example the following ones.</p>
<ol>
<li>(({Array#clip(fixnum, fixnum)})):</li>
</ol>
<p>['0', '1', '2', '3'].clip(1, 1) # => ['1', '2']</p>
<p>Thus (({a.clip(1, 1)})) would be a replacement for (({a[1..-2]})).</p>
<p>(It looks strange to have to convert a pair of numbers ((<em>m</em>)) and ((<em>n</em>)) into a range (({m..(-1-n)})) to simply ask an array to remove ((<em>m</em>)) elements from the beginning and ((<em>n</em>)) elements from the end.<br>
If <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Make Range act as a "lazy ordered set" (Open)" href="https://bugs.ruby-lang.org/issues/7545">#7545</a> is accepted, then the "(({a[1..-2]}))" syntax for "clipping" an array will make not much sense and maybe will not be possible.)</p>
<ol start="2">
<li>(({Array#from(fixnum)})), (({Array#till(fixnum)})):</li>
</ol>
<p>a = ['0', '1', '2', '3']<br>
a.from(1) # => ['1', '2', '3']<br>
a.till(1) # => ['0', '1']<br>
a.from(1).till(-2) # => ['1', '2']</p>
<p>In fact, in ((<em>Rails</em>)) (({ActiveSupport})) there are methods (({Array#from})) and (({Array#to})) like this, but unfortunately they do not accept negative indices.</p>
<p>((<em>Remark</em>)). It would also be possible to have (({Array#clip!})), (({Array#from!})), (({Array#till!})).<br>
=end</p> Ruby master - Feature #7444 (Open): Array#product_sethttps://bugs.ruby-lang.org/issues/74442012-11-27T14:44:28Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>I'd like to propose <code>Array#product_set</code> to return the product set of arrays (aka cartesian product)</p>
<pre><code>deck = [1..13, %i(spades hearts diamond clubs)].product_set
# => <#Enumerator ...>
deck.first(2) # => [[1, :spades], [2, :spades]]
</code></pre>
<p><code>product_set</code> would return an enumerator if no block is given. It should raise an error if an element of the array is not an Enumerable, like Array#transpose or #zip do.</p>
<p>Although <code>Array.product</code> would be acceptable too, I feel that an instance method of array is best in the case, in the same way that <code>transpose</code> is an instance method and not a class method.</p>
<p>The name "product_set" is a correct mathematical term. Although the synonym "cartesian_product" would also be acceptable, I propose "product_set" because it is shorter and cute too. I feel it is even clearer than <code>product</code>; the first time I head of <code>product</code> I was convinced that <code>[2,3,7].product # => 42</code>.</p>
<p>Addressing objections raised in <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: Array::zip (Rejected)" href="https://bugs.ruby-lang.org/issues/6499">#6499</a>:</p>
<ol>
<li>This is not for the sake of symmetry, but because often we have an array of the arrays we want a product of.</li>
</ol>
<p>It is cumbersome to write <code>arrays.first.product(*arrays[1..-1])</code> or similar and it hides what is going on.</p>
<p>Writing <code>arrays.product_set</code> is much nicer.</p>
<ol start="2">
<li>
<p>The goal is not mainly to get a lazy version, but more to make the API better. The fact that it returns an Enumerator if no block is given is just a bonus :-)</p>
</li>
<li>
<p>[].product_set.to_a # => [[]]</p>
</li>
</ol>
<p>This can be seen from a cardinality argument, or for example because <code>array.repeated_permutation(n) == Array.new(n, array).product_set.to_a</code> and <code>array.repeated_permutation(0) == [[]]</code>.</p> Ruby master - Feature #7377 (Open): #indetical? as an alias for #equal?https://bugs.ruby-lang.org/issues/73772012-11-17T09:47:45Zaef (Alexander E. Fischer)aef@raxys.net
<p>As my feature request <a class="issue tracker-2 status-6 priority-4 priority-default closed" title="Feature: #eql? and #equal? naming (Rejected)" href="https://bugs.ruby-lang.org/issues/7359">#7359</a> got rejected, here a more backward-compatible approach:</p>
<p>In my opinion the difference between #eql? and #equal? is really unintuitive. How about making their difference more obvious by giving one of them a more accurate name?</p>
<p>My proposal is to alias #equal? to #identical?.</p>
<p>I'll write a patch, if this is acceptable.</p> Ruby master - Feature #7314 (Assigned): Convert Proc to Lambda doesn't work in MRIhttps://bugs.ruby-lang.org/issues/73142012-11-09T01:30:19Zschneems (Richard Schneeman)
<p>I have code where I need to convert a proc to a lambda (i need to be able to return out of the block). I would expect that passing a proc into a lambda to return a lambda. When I run this code on MRI i do not get the result I would expect</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">my_proc</span> <span class="o">=</span> <span class="nb">proc</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span> <span class="p">}</span>
<span class="n">my_lambda</span> <span class="o">=</span> <span class="nb">lambda</span> <span class="o">&</span><span class="n">my_proc</span>
<span class="n">my_lambda</span><span class="p">.</span><span class="nf">lambda?</span>
</code></pre>
<p>The result is <code>false</code> but I would expect it to be <code>true</code></p>
<p>There is currently a way to turn a proc into a lambda in MRI like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">convert_to_lambda</span> <span class="o">&</span><span class="n">block</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span>
<span class="n">obj</span><span class="p">.</span><span class="nf">define_singleton_method</span><span class="p">(</span><span class="ss">:_</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span><span class="p">.</span><span class="nf">method</span><span class="p">(</span><span class="ss">:_</span><span class="p">).</span><span class="nf">to_proc</span>
<span class="k">end</span>
</code></pre>
<p>But this feels like a hack, and is not supported across other implementations. I would expect that passing a proc into a lambda to return a lambda, I believe it is a bug.</p> Ruby master - Feature #7149 (Open): Constant magic for everyone.https://bugs.ruby-lang.org/issues/71492012-10-13T02:46:15ZAnonymous
<p>I noticed that certain objects have constant magic: When they are first assigned to a constant, they acquire a name property equal to the constant name string. I only know about Class and Struct objects behaving this way. I like this behavior, because I like to be able to say something like:</p>
<p>Adenosine = ChemicalSpecies.new initial_concentration: 5.micromolar<br>
Adenosine.name #=> "Adenosine"</p>
<p>I like it so much, that I wrote a library (I call it ConstantMagicErsatz) for myself that searches whole namespace for the new objects assigned to constants. But searching whole wild namespace has its pitfalls. It is a wildly difficult workaround to get the candy I want. I am dreaming about just being able to say:</p>
<p>class ChemicalSpecies<br>
constant_magic true<br>
end</p>
<p>and imbue ChemicalSpecies with the same constant magic ability that Class and Struct classes have. Could it be made possible, please?</p> Ruby master - Feature #6869 (Open): Do not treat `_` parameter exceptionallyhttps://bugs.ruby-lang.org/issues/68692012-08-15T06:50:54Zalexeymuranov (Alexey Muranov)
<p>I started by commenting on <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Don't warn for unused variables starting with _ (Closed)" href="https://bugs.ruby-lang.org/issues/6693">#6693</a>, but i have realized that this is a slightly different request.</p>
<p>I propose to not treat the variable name "<code>_</code>" exceptionally. Current behavior:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="p">{</span><span class="mi">0</span><span class="o">=></span><span class="mi">1</span><span class="p">}.</span><span class="nf">each_with_index</span> <span class="p">{</span> <span class="o">|</span><span class="n">_</span><span class="p">,</span><span class="n">_</span><span class="o">|</span> <span class="nb">p</span> <span class="n">_</span> <span class="p">}</span> <span class="c1"># [0, 1]</span>
</code></pre>
<p>prints "[0, 1]", but</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="p">{</span><span class="mi">1</span><span class="o">=></span><span class="mi">2</span><span class="p">}.</span><span class="nf">each_with_index</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="p">,</span><span class="n">x</span><span class="o">|</span> <span class="nb">p</span> <span class="n">x</span> <span class="p">}</span> <span class="c1"># SyntaxError: (eval):2: duplicated argument name</span>
</code></pre>
<p>raises "SyntaxError: (eval):2: duplicated argument name".</p>
<p>Similarly for methods:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">_</span><span class="p">,</span> <span class="n">_</span><span class="p">)</span>
<span class="n">_</span>
<span class="k">end</span>
<span class="n">f</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="c1"># => 0</span>
<span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
<span class="n">x</span>
<span class="k">end</span> <span class="c1"># => SyntaxError: (eval):2: duplicated argument name</span>
</code></pre>
<p>Observe also that the use of repeated <code>_</code> parameter is not consistent between methods and blocks: for methods the value is the first assigned value, and for blocks it is the array of all the assigned values.</p>
<ol>
<li>I propose to use the same rule for all variables, without distinguishing <code>_</code> specially.</li>
</ol>
<p>In particular i propose to allow to repeat any variable, not only <code>_</code>, in block or method arguments without raising an error.</p>
<p>There may be several solutions what the repeated argument will hold: it may hold the array of all assigned values, the first assigned value, the last assigned value, the first non-nil assigned value, or the last non-nil assigned value.</p>
<ol start="2">
<li>
<p>I propose to treat repeated arguments in methods and in blocks the same way (do not know which one).</p>
</li>
<li>
<p>For unused variables i propose to introduce a special placeholder, for example "<code>-</code>" not followed by anything other than a delimiter (comma or bracket):</p>
</li>
</ol>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="n">each_with_index</span> <span class="p">{</span> <span class="o">|-</span><span class="p">,</span> <span class="n">value</span><span class="o">|</span> <span class="nb">puts</span> <span class="n">value</span> <span class="p">}</span>
<span class="o">-</span><span class="p">,</span> <span class="o">-</span><span class="p">,</span> <span class="n">suffix</span> <span class="o">=</span> <span class="n">parse</span><span class="p">(</span><span class="nb">name</span><span class="p">)</span>
</code></pre> Ruby master - Feature #6842 (Assigned): Add Optional Arguments to String#striphttps://bugs.ruby-lang.org/issues/68422012-08-07T20:24:20Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
One of the very few things I miss from the ol' php days many years ago, was the ability to easily strip arbitrary characters from the ends of string using trim(). Typically, this is whitespace characters, and #strip currently fulfils that use case, but there are also instances where it'd be nice to be able to strip any range of characters from the ends of a string. It goes well with Array#join as often when joining strings with a delimiter, you want to make sure those strings don't already begin or end with that character.</p>
<p>For a full-featured #strip, I'd like to see it have the option of accepting both an Array or String. If a string is provided, each character in that string will be stripped. If an array of strings is given, each element of the array is stripped from the ends of the string - this allows for multi-character delimiters for example. Of course you could go really nuts and supports regex as well (or instead of arrays). To demonstrate the difference...</p>
<pre><code>"<b>bold text</b>".strip("</b>") #=> "old text"
"<b>bold text</b>".strip(["<b>", "</b>"]) #=> "bold text"
"<em><b>bold text</b></em>".strip(["<b>", "</b>", "<em>", "</em>"]) #=> "bold text"
"<em><b>bold text</b></em>".strip(/<\/?.+?>/) #=> "bold text"
</code></pre>
<p>A simple real-world example; this is actually what I was wanting to do right before I came here to raise this feature request, but there's been all kinds of other use cases I've hit in the past:</p>
<pre><code>['some', '/chunked', 'path/'].map{ |v| v.strip('/') }.join('/') #=> "some/chunked/path"
</code></pre>
<p>File#join does something similar, but when you need control over the joining character, this is the way you'd do it.</p>
<p>I've lost count of how many times I've wanted this in Ruby, and there's really no nice workaround. Here's an example on StackOverflow of someone asking how to achieve this stripping behaviour in ruby: <a href="http://stackoverflow.com/questions/3453262/how-to-strip-leading-and-trailing-quote-from-string-in-ruby" class="external">http://stackoverflow.com/questions/3453262/how-to-strip-leading-and-trailing-quote-from-string-in-ruby</a></p>
<p>Obviously, you'd do the same for #lstrip and #rstrip, and all the mutable variants (#strip!, #lstrip!, #rstrip!). Looking forward to others thoughts on this one.<br>
=end</p> Ruby master - Feature #6817 (Open): Partial applicationhttps://bugs.ruby-lang.org/issues/68172012-07-31T15:38:35Zcitizen428 (Michael Kohl)citizen428@gmail.com
<p>I know that what I propose here is a significant change to Ruby, but it's part of my ongoing quest to get some more functional programming features into Ruby (see also <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: Array#zip_with (Assigned)" href="https://bugs.ruby-lang.org/issues/4539">#4539</a> and <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: public #self (Closed)" href="https://bugs.ruby-lang.org/issues/6373">#6373</a>).</p>
<p>I was wondering if it would make sense to maybe introduce partial application to Ruby? So that instead of</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">).</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">2</span> <span class="p">}</span>
</code></pre>
<p>or the somewhat unwieldy</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">).</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="mi">2</span><span class="p">.</span><span class="nf">method</span><span class="p">(:</span><span class="o">+</span><span class="p">))</span>
</code></pre>
<p>one could just write</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">3</span><span class="p">).</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="mi">2</span><span class="p">.</span><span class="nf">+</span><span class="p">)</span>
</code></pre>
<p>which I think has a quite rubyish feel to it. I have a POC implementation in Ruby (I tried it with various <code>Fixnum</code> methods) over at <a href="http://citizen428.net/blog/2012/07/30/ruby-left-section-for-infix-operators" class="external">my blog</a>, but that was just a quick hack and obviously I don't want to monkey-patch every method with arity 1, but it was a nice way of exploring possible syntax.</p> Ruby master - Feature #6641 (Open): Hash.auto constructorhttps://bugs.ruby-lang.org/issues/66412012-06-25T09:34:06Ztrans (Thomas Sawyer)
<p>=begin<br>
It is not uncommon to need a Hash following the pattern:</p>
<p>Hash.new{ |h,k| h[k]={} }</p>
<p>Another common example:</p>
<p>Hash.new{ |h,k| h[k]=[] }</p>
<p>This is common enough that it would very nice if we could have a more concise form, e.g.</p>
<p>Hash.auto{ {} }</p>
<p>Or for the second example:</p>
<p>Hash.auto{ [] }</p>
<p>Pure Ruby implementation is pretty simple:</p>
<p>def Hash.auto<br>
Hash.new{ |h,k| h[k] = yield }<br>
end</p>
<p>I think it would be nice to have in Core.</p>
<p>This is secondary, but it just occurred to me. Could there even be a literal notation for the above? Something like:</p>
<p>{}([])</p>
<p>?<br>
=end</p> Ruby master - Feature #6277 (Assigned): Hash#convert_keyhttps://bugs.ruby-lang.org/issues/62772012-04-11T01:12:20Ztrans (Thomas Sawyer)
<p>=begin<br>
Many times a hash with uniform keys is needed (or is at least preferable) for a particular usecase. To this end I propose ((%Hash#convert_key%)).</p>
<p>h = {}<br>
h.convert_key{ |k| k.to_sym }<br>
h['a'] = 1<br>
h.update('b'=>2)<br>
h #=> {:a=>1, :b=>2}</p>
<p>The idea is similar in concept to ((%#default_proc%)).</p>
<p>Others solutions to fill this need have been tried and used, but almost exclusively are in the form of a new class. Most notable is Rails HashWithIndifferentAccess. But ((%#convert_key%)) has much greater flexibility since keys can be converted to anything.<br>
=end</p> Ruby master - Feature #5970 (Assigned): Add Enumerable#join with same semantics as Array#joinhttps://bugs.ruby-lang.org/issues/59702012-02-05T17:27:39Znow (Nikolai Weibull)now@disu.se
<p>Currently, to join the elements of an Enumerable, you need to call #to_a on the Enumerable and then #join the result. With Enumerable#join one wouldn’t need need to create an intermediate Array.</p> Ruby master - Feature #5749 (Assigned): new method String#match_all neededhttps://bugs.ruby-lang.org/issues/57492011-12-12T18:03:57Zyimutang (Joey Zhou)
<p>The String class should contain an instance method 'match_all', which is a mixture of 'match' and 'scan'.</p>
<p>The method 'scan' is not a very powerful tool, its result(the yielding thing) is just a matched string or an array of captured strings.</p>
<p>p 'a1bc2de3f'.scan(/(.)\d(.)/) # [["a", "b"], ["c", "d"], ["e", "f"]]</p>
<p>If the regex argument contains groups, I even cannot get the whole matched string, and no information about the matched offsets.</p>
<p>So, a 'match_all' is very necessary. It scan the string, finding every matched, and yielding <em>MatchData instance</em> to the following block.</p>
<p>Here's a simple implemention in Ruby:</p>
<p>class String<br>
def match_all(re,i=0)<br>
if block_given?<br>
while m = self.match(re,i)<br>
yield m<br>
i = m.end(0)<br>
end<br>
return self<br>
else<br>
ary = []<br>
while m = self.match(re,i)<br>
ary << m<br>
i = m.end(0)<br>
end<br>
return ary<br>
end<br>
end<br>
end</p>
<p>However, it is not efficient in the 'while m = self.match(re,i)' way, because it scan the string again and again. If string is UTF8-encoded and contains out-of-ASCII characters, I'm afraid getting the start index of it is so expensive.</p>
<p>So, I think a built-in 'match_all' method, which behaves just like 'scan' but yield MatchData, is needed.</p>
<p>Please consider it, thank you!</p> Ruby master - Feature #5741 (Assigned): Secure Erasure of Passwordshttps://bugs.ruby-lang.org/issues/57412011-12-11T06:02:13ZMartinBosslet (Martin Bosslet)Martin.Bosslet@gmail.com
<p>In other languages it is considered good practice to securely erase<br>
passwords immediately after they were used. Imagine authentication<br>
in a web app - ultimately a String containing the password arrives<br>
at the server, where it will be processed and compared to some<br>
previously stored value. After this is done, there is no need to<br>
store these password Strings any longer, so they should be<br>
discarded right away (more on why later).</p>
<p>In C, you would simply overwrite the array of bytes with zeroes or<br>
random values. In Java, Strings are immutable, that's why there it<br>
is common practice to use char[] for all things password and overwrite<br>
them when done.</p>
<p>Currently, there is no way in Ruby to overwrite the memory that<br>
was used by a String. String#clear and String#replace both use<br>
str_discard internally, which only frees the underlying pointer<br>
without overwriting it.</p>
<p>The problem with not erasing passwords is this: the contents of the<br>
String stay in memory until they are finally GC'ed. But even then<br>
only the pointer will be freed, leaving the contents mostly intact<br>
until the memory is reclaimed and overwritten later on.</p>
<p>This could be exploited if an attacker had access to the memory of<br>
the server. This could happen in many ways: a core dump after a<br>
crash, access to the host if the server runs in a VM, or even by<br>
deep-freezing the DRAM :) [1]</p>
<p>It could be argued that given the examples above, much more<br>
devastating attacks would be possible since in all of those<br>
cases you more or less have physical access to the machine. But<br>
I would still consider this to be a valid concern, if not only<br>
for the reason of never opening additional attack surfaces if<br>
they can be avoided relatively easily.</p>
<p>I also found [2], which seems to show that Python deals with<br>
similar problems and it also contains more background info.</p>
<p>Eric Hodel and I discussed this yesterday and Eric came up with<br>
a C extension that can be used to illustrate the problem (attached).</p>
<p>If you inspect the resulting core dump, you will find the following:</p>
<ul>
<li>the untouched String remains in memory fully intact</li>
<li>the String#clear'ed String remains to a large extent, typically the<br>
first character is missing - so if you typed "PASSWORD", search for<br>
"ASSWORD" (unintentional pun) instead</li>
<li>The String#clear_secure'ed will have been completely erased, no<br>
traces remain</li>
</ul>
<p>My questions:</p>
<ol>
<li>Would you agree that we need this functionality?</li>
<li>Where would we ideally place it? I'm not sure whether<br>
String is the perfect place, but on the other hand, String<br>
is the only place where we have access to the implementation<br>
details.</li>
<li>Are there better alternative ways how we could achieve this?</li>
</ol>
<p>[1] <a href="http://www.schneier.com/blog/archives/2008/02/cold_boot_attac.html" class="external">http://www.schneier.com/blog/archives/2008/02/cold_boot_attac.html</a><br>
[2] <a href="http://stackoverflow.com/questions/728164/securely-erasing-password-in-memory-python" class="external">http://stackoverflow.com/questions/728164/securely-erasing-password-in-memory-python</a></p> Ruby master - Feature #5643 (Assigned): require/load options and binding optionhttps://bugs.ruby-lang.org/issues/56432011-11-17T07:41:01Ztrans (Thomas Sawyer)
<p>Current Kernel#load is defined as:</p>
<pre><code>load(filename, wrap=false)
</code></pre>
<p>I purpose that it be modified to work as option argument, e.g.</p>
<pre><code>load(filename, :wrap=>true)
</code></pre>
<p>Right off the bat this has better name connascence.</p>
<p>Then support an additional option <code>:binding</code>, such that, given:</p>
<pre><code>$ cat lib/example.rb
def a
1
end
</code></pre>
<p>then</p>
<pre><code>class X
load('example.rb', :binding=>binding)
end
X.new.a #=> 1
</code></pre>
<p>The binding option should also work with #require (which would also support option parameter) differing from #load in the it would only allow the feature to be loaded once per-binding's self regardless of being required again.</p>
<p>This ability would greatly benefit systems that need "plugin" capability. Presently, a great deal of coding has to go into simulating this functionality to create plugin systems, which are often imperfect nor robust.</p> Ruby master - Feature #5582 (Assigned): Allow clone of singleton methods on a BasicObjecthttps://bugs.ruby-lang.org/issues/55822011-11-07T12:34:13Zthinkerbot (Simon Chiang)simon.a.chiang@gmail.com
<p>Currently I do not know of a way to implement something like 'clone' on a BasicObject subclass. This is as close as I've gotten but as you can see the singleton methods are not propagated to the clone.</p>
<pre><code>require 'test/unit'
class Context < BasicObject
def _singleton_class_
class << self
SINGLETON_CLASS = self
def _singleton_class_
SINGLETON_CLASS
end
end
_singleton_class_
end
def _class_
_singleton_class_.superclass
end
def _extend_(mod)
mod.__send__(:extend_object, self)
end
def _initialize_clone_(orig)
# set variables as needed
end
def _clone_
clone = _class_.allocate
clone._initialize_clone_(self)
_singleton_class_.included_modules.each {|mod| clone._extend_ mod }
clone
end
end
class ContextTest < Test::Unit::TestCase
module A
def a
:a
end
end
def test__clone__inherits_modules
context = Context.new
context._extend_ A
clone = context._clone_
assert_equal :a, clone.a
end
def test__clone__inherits_singleton_methods
context = Context.new
def context.a
:a
end
clone = context._clone_
assert_equal :a, clone.a # fails
end
end
</code></pre>
<p>Is there a way to do this that I don't see? If not, then I request that a way be added - perhaps by allowing the singleton_class to be set somehow.</p>
<p>In my case I am using Context as the context for a dsl where methods write to a target (an instance variable). I want to be able to clone a context such that I can have multiple contexts with the same methods, including extensions and singletons, that write to different targets.</p>
<p>Thank you.</p> Ruby master - Feature #5558 (Assigned): String#% strange arity errorshttps://bugs.ruby-lang.org/issues/55582011-11-03T10:25:55Ztrans (Thomas Sawyer)
<p>When the number of arguments do not match the number of % parameters, the String#% method has some odd behavior.</p>
<p>When too many, it seems to work fine, ignoring the extra arguments.</p>
<p>"%s" % [1,2] #=> "1"</p>
<p>But if <code>$DEBUG = true</code>,</p>
<p>"%s" % [1,2] #=> ArgumentError: too many arguments for format string</p>
<p>That doesn't seem right. Is it an error or isn't it?</p>
<p>For too few arguments it is always an error:</p>
<p>"%s" % [] #=> ArgumentError: too few arguments</p>
<p>Personally, I think it should use '' for missing arguments. That would make it more flexible in practice.</p>
<p>I consider the first $DEBUG issue a bug, and the later a feature. But I'll just call it a feature altogether to make things easier.</p> Ruby master - Feature #5445 (Assigned): Need RUBYOPT -r before ARGV -rhttps://bugs.ruby-lang.org/issues/54452011-10-14T00:47:09Ztrans (Thomas Sawyer)
<p>Libraries given by -r options in RUBYOPT should be loaded before ones in direct command line arguments.</p>
<p>I use a custom load system for development that I have been using for years and it works very well for me. But Ruby has some edge cases that prevents it from being feature complete. One of these is the order in which RUBYOPT is applied vs. -r command line option.</p>
<p>My custom loader is too large to include here, so I will simply demonstrate the problem with simple sample code:</p>
<p>$ cat req.rb<br>
p "Custom Require"</p>
<p>module Kernel<br>
alias :require0 :require</p>
<pre><code>def require(*a)
puts "Kernel#require"
p a
require0(*a)
end
class << self
alias :require0 :require
def require(*a)
puts "Kernel.require"
p a
require0(*a)
end
end
</code></pre>
<p>end</p>
<p>If we load this via RUBYOPT, the result is:</p>
<p>$ RUBYOPT=-r./req.rb ruby -rstringio -e0<br>
Custom Require</p>
<p>But if we load via -r the result is:</p>
<p>$ ruby -r./req.rb -rstringio -e0<br>
Custom Require<br>
Kernel#require<br>
["stringio"]</p>
<p>I would ask that the output of both invocations to be identical.</p>
<p>(Note, the -T option should still allow RUBYOPT to be omitted regardless.)</p> Ruby master - Feature #5389 (Assigned): New method Enumerator#iteratehttps://bugs.ruby-lang.org/issues/53892011-10-03T20:25:16Zyimutang (Joey Zhou)
<p>If we want to iterate over the elements of a enumerable object with <em>multiple</em> blocks, we can use the Enumerator class.</p>
<p>A method 'iterate' is required, we can write it in Ruby:</p>
<pre><code>class Enumerator
def iterate
yield_value = self.next
return_value = yield yield_value
self.feed return_value
self
end
end
</code></pre>
<p>Well, here is an example:</p>
<pre><code>array = (1..10).to_a
enum = array.map!
loop do
enum.iterate {|n| n + 10 }
enum.iterate {|n| n * 2 }
enum.iterate {|n| -n }
end
p array # => [11, 4, -3, 14, 10, -6, 17, 16, -9, 20]
</code></pre>
<p>We want to map an array: the 1st element use blk1, the 2nd use blk2, the 3rd use blk3...</p>
<p>I think this Enumerator#iterate method is sometimes useful, so would you please introduce it into the language core?</p> Ruby master - Feature #5064 (Assigned): HTTP user-agent classhttps://bugs.ruby-lang.org/issues/50642011-07-21T13:10:00Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>Currently there are some problems with Net::HTTP:</p>
<ul>
<li>Too many ways to use (user confusion)</li>
<li>No automatic support for HTTPS (must conditionally set use_ssl)</li>
<li>No automatic support for HTTPS peer verification (must be manually set)</li>
<li>Single-connection oriented</li>
<li>No support for redirect-following</li>
<li>No support for HTTP/1.1 persistent connection retry (RFC 2616 8.1.4)</li>
<li>No automatic support for HTTP proxies</li>
<li>No automatic support for authentication (must be set per-request)</li>
</ul>
<p>Additionally the style of the API of Net::HTTP makes it difficult to take advantage of persistent connections. The user has to store the created connection and manually handle restarting the connection if it has timed out or is closed by the server.</p>
<p>RFC 2616 8.1.1 has a large section explaining the benefits of persistent connections, but while Net::HTTP implements persistent connections they could be easier for users to implement with next work.</p>
<p>I've implemented support for many of these additional features of Net::HTTP in various projects and I'd like Ruby to have the features required to make a useful HTTP user-agent built-in.</p>
<p>The agent should have the following responsibilities:</p>
<ul>
<li>Make or reuse connections based on [host, port, SSL enabled]</li>
<li>Automatically enable SSL for https URIs</li>
<li>Automatically enable SSL peer verification for SSL connections</li>
<li>Limit number of persistent connections per host</li>
<li>Follow redirects</li>
<li>Retry when a persistent connection fails</li>
<li>Automatically configure proxies</li>
<li>Automatically use authentication</li>
<li>Callbacks for various options connect</li>
</ul>
<p>The agent may add the following responsibilities:</p>
<ul>
<li>Default headers for all requests</li>
<li>HTTP cookies</li>
<li>Tracking history</li>
<li>Logging</li>
</ul>
<p>I don't think any of these features are critical as they are implementable by users via callbacks.</p>
<p>The agent would have the following configurable items:</p>
<ul>
<li>Number of connections per host</li>
<li>Depth of redirects followed</li>
<li>Persistent connection retries (none, HTTP/1.1 (default), always)</li>
<li>Proxy host, port, user, password</li>
</ul>
<p>I think the class should be called Net::HTTP::Agent.</p>
<p>Basic use would look something like this:</p>
<p>uris = [<br>
URI('http://example/1'),<br>
URI('http://example/2'),<br>
URI('https://secure.example'),<br>
]</p>
<p>agent = Net::HTTP::Agent.new</p>
<p>uris.map do |uri|<br>
agent.get uri # Returns Net::HTTPResponse<br>
end</p>
<p>For special requests a Net::HTTPRequest could be constructed:</p>
<p>req = Net::HTTP::Get.new uri.request_uri</p>
<a name="do-something-special-with-req"></a>
<h1 >do something special with req<a href="#do-something-special-with-req" class="wiki-anchor">¶</a></h1>
<p>agent.request req</p>
<p>The agent should support GET, POST, etc. directly through API methods. I think the API should look something like this:</p>
<p>def get uri_or_string, query = nil, headers = nil</p>
<a name="Same-for-other-requests-with-no-body"></a>
<h1 >Same for other requests with no body<a href="#Same-for-other-requests-with-no-body" class="wiki-anchor">¶</a></h1>
<h1></h1>
<a name="query-may-be-a-Hash-or-String"></a>
<h1 >query may be a Hash or String<a href="#query-may-be-a-Hash-or-String" class="wiki-anchor">¶</a></h1>
<a name="How-query-param-vs-query-string-in-URI-is-used-is-undecided"></a>
<h1 >How query param vs query string in URI is used is undecided<a href="#How-query-param-vs-query-string-in-URI-is-used-is-undecided" class="wiki-anchor">¶</a></h1>
<p>def post uri_or_string, data, headers = nil</p>
<a name="same-for-other-requests-with-a-body"></a>
<h1 >same for other requests with a body<a href="#same-for-other-requests-with-a-body" class="wiki-anchor">¶</a></h1>
<h1></h1>
<a name="data-may-be-a-String-IO-or-Hash"></a>
<h1 >data may be a String, IO or Hash<a href="#data-may-be-a-String-IO-or-Hash" class="wiki-anchor">¶</a></h1>
<a name="How-data-format-is-chosen-is-undecided"></a>
<h1 >How data format is chosen is undecided<a href="#How-data-format-is-chosen-is-undecided" class="wiki-anchor">¶</a></h1>
<p>SSL options, proxy options, timeouts and similar options should exist on Net::HTTP::Agent and be set on new connections as they are made.</p>
<p>I've implemented most of these features in mechanize as Mechanize::HTTP::Agent. The Agent class in mechanize is bigger than is necessary and would need to be cut-down for inclusion in Ruby as Net::HTTP::Agent</p>
<p><a href="https://github.com/tenderlove/mechanize/blob/master/lib/mechanize/http/agent.rb" class="external">https://github.com/tenderlove/mechanize/blob/master/lib/mechanize/http/agent.rb</a></p>
<p>Mechanize depends on net-http-persistent to provide HTTP/1.1 retry support and connection management:</p>
<p><a href="https://github.com/drbrain/net-http-persistent/blob/master/lib/net/http/persistent.rb" class="external">https://github.com/drbrain/net-http-persistent/blob/master/lib/net/http/persistent.rb</a></p>
<p>Portions of net-http-persistent should be patches of Net::HTTP, for example #idempotent? #can_retry?, #reset and portions of #request. Other parts (connection management) should be moved to Net::HTTP::Agent.</p>
<p>net-http-persistent provides a separate connection list per thread. I would like Net::HTTP::Agent to be multi-thread friendly but implementing this in another way would be fine.</p>
<p>As an addendum, open-uri and mechanize should be written to take advantage of Net::HTTP::Agent on order to guide useful implementation.</p> Ruby master - Feature #4818 (Assigned): Add method marshalable?https://bugs.ruby-lang.org/issues/48182011-06-03T11:07:15Zyimutang (Joey Zhou)
<p>Some objects can not be marshaled. Maybe there should be a method to tell it.</p>
<p>hash = Hash.new {|h,k| k * 2}</p>
<p>this hash can't be marshaled because it has a default proc. If existing such method:</p>
<p>Marshal.marshalable?(hash) #=> method "Marshal.marshalable?"<br>
hash.marshalable? #=> method "Kernel#marshalable?"</p>
<p>If you think the method name hard to spell, maybe get a synonym "dumpable?"</p> Ruby master - Feature #4592 (Assigned): Tempfileを直接保存したいhttps://bugs.ruby-lang.org/issues/45922011-04-21T16:43:31Zxibbar (Takeyuki FUJIOKA)xibbar@gmail.com
<p>=begin<br>
Tempfileは一時ファイルなので、プロセスが消えたり、#closeすると、<br>
ファイルが消えてしまいます。<br>
Tempfileのデータを保存するために<br>
一旦読みだして、書き込み用に別ファイルを開いて、<br>
そこに書きこまなければいけません。<br>
これが小さいファイルだったらいいのですが、<br>
大きいファイルになると、<br>
Tempfile#save みたいなメソッドを用意して、<br>
closeと同時に保存ができると、<br>
読みだして書きこむという無駄をなくすことができます。<br>
10MB程度だったらいいのですが、500MとかのTempfileだと<br>
かなり有効なメソッドだと思います。</p>
<p>#save とか #save! とか、何がいいかは議論の余地があると思います。<br>
=end</p> Ruby master - Feature #4521 (Assigned): NoMethodError#message may take very long to executehttps://bugs.ruby-lang.org/issues/45212011-03-25T04:59:14Zadiel.mittmann (Adiel Mittmann)adiel@inf.ufsc.br
<p>=begin<br>
When a non-existing method is called on an object, NoMethodError is risen. If you call #message, however, your code may use up all CPU for a very long time (in my case, up to a few minutes).</p>
<p>I narrowed the problem down to this code in error.c (SVN snapshot) in the function name_err_mesg_to_str():</p>
<p>d = rb_protect(rb_inspect, obj, 0);<br>
if (NIL_P(d) || RSTRING_LEN(d) > 65) {<br>
d = rb_any_to_s(obj);<br>
}</p>
<p>The problem is that, for a complex object, #inspect may take very long to execute, only to have its results thrown away because they will be larger than 65 characters.</p>
<p>Of course I can write a #to_s for all my objects, but the point is that I didn't call #to_s or #inspect, I called #message on an exception object, which then takes a few minutes just to return a short string.</p>
<p>Needless to say, this might be easy to spot in a simple example, but once you're writing a web application that suddenly freezes for one minute with no apparent reason, you're all but clueless as to what's going on. (The first time this happened, I didn't even know that something would eventually show up on the screen -- I thought it was an infinite loop).</p>
<p>Here's an example code that shows this behavior:</p>
<p>require 'nokogiri'<br>
class A<br>
def x<br>
@xml = Nokogiri::XML(File.new('baz.xml', 'rb').read())<br>
foo()<br>
end<br>
end<br>
A.new().x()<br>
a.x</p>
<p>Here, the time it takes for Ruby to print out the message that #foo doesn't exist is proportional to the size of baz.xml.</p>
<p>As a comparison, Python doesn't seem to do this. Take the following code:</p>
<p>class Test:<br>
def <strong>str</strong>(self):<br>
return "hello"<br>
a = Test()<br>
print a<br>
print a.x()</p>
<p>If you execute it, this is the result:</p>
<p>hello<br>
Traceback (most recent call last):<br>
File "test.py", line 6, in <br>
print a.x()<br>
AttributeError: Test instance has no attribute 'x'</p>
<p>It uses the method <strong>str</strong> to convert the object to a string when necessary, but doesn't use it when printing out the message stating that the attribute doesn't exist.</p>
<p>One obvious way to fix this would be to always print out the simpler representation given by rb_any_to_s.<br>
=end</p> Ruby master - Feature #4514 (Assigned): #deep_clone and #deep_dup for Objectshttps://bugs.ruby-lang.org/issues/45142011-03-21T19:23:02Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
There's often a need to do a deep clone of an object, especially of Hash/Array trees. The typical work around to the lack of this functionality is to Marshall and then Unmarshall (e.g. Marshal::load(Marshal::dump(self)) ), which incurs more overhead than it probably should, and is not very semantic. My suggestion is to either provide #deep_clone and #deep_dup methods on the Object class, or to at least provide equivalent functionality for Hashes and Arrays, such as possibly a #deep_merge method for Hash. The exact implantation is not a large concern of mine; I'll let the experts determine the best method of achieving the desired outcome.<br>
=end</p>