Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112024-04-03T14:24:53ZRuby Issue Tracking System
Redmine Ruby master - Feature #20408 (Open): Add heap_live_slots to GC.stat_heaphttps://bugs.ruby-lang.org/issues/204082024-04-03T14:24:53Zmk (Matthias Käppler)
<p><code>GC.stat</code> exposes a <code>heap_live_slots</code> metric that returns the number of live objects occupying eden slots.</p>
<p>Because the slot size was fixed to <code>RVALUE_SIZE</code>, this allowed for some basic approximations of how many bytes were live/in-use (<code>heap_live_slots * RVALUE_SIZE</code>).<br>
This could furthermore be "embellished" by adding malloc'ed memory for those objects that were larger than a 40B slot (we track this via a custom CRuby patch).</p>
<p>However, with the addition of Variable Width Allocations (<a href="https://bugs.ruby-lang.org/issues/18239" class="external">https://bugs.ruby-lang.org/issues/18239</a>), this does not work anymore because we don't know how <code>heap_live_slots</code> distributes over all pools that use different slot sizes.</p>
<p>This could be addressed by also adding <code>heap_live_slots</code> (and for symmetry: <code>heap_free_slots</code>) to <code>GC.stat_heap</code>. The sum of all live slots per pool should equal <code>GC.stat[:heap_live_slots]</code>.</p> Ruby master - Feature #20164 (Open): Add Exception#deconstruct_keyshttps://bugs.ruby-lang.org/issues/201642024-01-08T20:56:25ZDan0042 (Daniel DeLorme)
<p>It would be convenient to perform pattern matching with exception classes. So <code>Exception#deconstruct_keys</code> should return a hash with <code>:message</code> (original_message) as well as any other keys specific to the exception subclass.</p>
<p>Examples:</p>
<pre><code>begin
#code
rescue => err
case err
in StandardError(message: /Permission denied/)
abort "please select a different file"
in NameError(name: :foo)
retry if require "foo_helper
else
raise
end
end
</code></pre> Ruby master - Bug #20154 (Open): aarch64: configure overrides `-mbranch-protection` if it was set...https://bugs.ruby-lang.org/issues/201542024-01-05T21:25:03Zjprokop (Jarek Prokop)
<p>Recently a GH PR was merged <a href="https://github.com/ruby/ruby/pull/9306" class="external">https://github.com/ruby/ruby/pull/9306</a> For PAC/BTI support on ARM CPUs for Coroutine.S.</p>
<p>Without proper compilation support in configure.ac it segfaults Ruby with fibers on CPUs where PAC is supported: <a href="https://bugs.ruby-lang.org/issues/20085" class="external">https://bugs.ruby-lang.org/issues/20085</a></p>
<p>At the time of writing, configure.ac appends the first option from a list for flag <code>-mbranch-protection</code> that successfully compiles a program <a href="https://github.com/ruby/ruby/blob/master/configure.ac#L829" class="external">https://github.com/ruby/ruby/blob/master/configure.ac#L829</a>,<br>
to XCFLAGS and now also ASFLAGS to fix issue 20085 for Ruby master.</p>
<p>This is suboptimal for Fedora as we set -mbranch-protection=standard by default in C{,XX}FLAGS:</p>
<pre><code>CFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Werror=implicit-function-declaration -Werror=implicit-int -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer '
export CFLAGS
CXXFLAGS='-O2 -flto=auto -ffat-lto-objects -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-U_FORTIFY_SOURCE,-D_FORTIFY_SOURCE=3 -Wp,-D_GLIBCXX_ASSERTIONS -specs=/usr/lib/rpm/redhat/redhat-hardened-cc1 -fstack-protector-strong -specs=/usr/lib/rpm/redhat/redhat-annobin-cc1 -mbranch-protection=standard -fasynchronous-unwind-tables -fstack-clash-protection -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer'
export CXXFLAGS
</code></pre>
<p>And the appended flag overrides distribution's compilation configuration, which in this case ends up omitting BTI instructions and only using PAC.</p>
<p>Would it make sense to check if such flags exist and not overwrite them if they do?</p>
<p>Serious proposals:</p>
<ol>
<li>Simplest fix that does not overwrite what is set in the distribution and results in higher security is simply prepending the list of options with <code>-mbranch-protection=standard</code>, it should cause no problems on ARMv8 CPUs and forward, BTI similarly to PAC instructions result into NOP, it is only extending the capability.</li>
</ol>
<p>See attached 0001-aarch64-Check-mbranch-protection-standard-first-to-u.patch</p>
<ol start="2">
<li>Other fix that sounds more sane IMO and dodges this kind of guessing where are all the correct places for the flag is what another Fedora contributor Florian Weimer suggested: <a href="https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/message/CVTNF2OQCL3XZHUUFNYMDK6ZEF2SWUEN/" class="external">https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/message/CVTNF2OQCL3XZHUUFNYMDK6ZEF2SWUEN/</a>
</li>
</ol>
<p>"The reliable way to do this would be to compile a C file and check<br>
whether that enables __ARM_FEATURE_PAC_DEFAULT, and if that's the case,<br>
define a <em>different</em> macro for use in the assembler implementation.<br>
This way, you don't need to care about the exact name of the option."</p>
<p>IOW instead of using _<em>ARM_FEATURE</em>* directly in that code, define a macro in the style of "USE_PAC" with value of the feature if it is defined, I think that way we shouldn't need to append ASFLAGS anymore.</p>
<p>However it's also important to catch the value of those macros as their values have meaning, I have an idea how to do that but I'd get on that monday earliest.</p> Ruby master - Feature #19787 (Open): Add Enumerable#uniq_map, Enumerable::Lazy#uniq_map, Array#un...https://bugs.ruby-lang.org/issues/197872023-07-29T14:13:00Zjoshuay03 (Joshua Young)
<p>I would like to propose a collection of new methods, <code>Enumerable#uniq_map</code>, <code>Enumerable::Lazy#uniq_map</code>, <code>Array#uniq_map</code> and <code>Array#uniq_map!</code>.</p>
<p>TL;DR: It's a drop in replacement for <code>.map { ... }.uniq</code>, with (hopefully) better performance.</p>
<p>I've quite often had to map over an array and get its unique elements. It occurred to me when doing so recently that Ruby doesn't have a short form method for doing that, similar to how <code>.flat_map { ... }</code> replaces <code>.map { ... }.flatten</code> and <code>.filter_map { ... }</code> replaces <code>.map { ... }.compact</code> (with minor differences). I think these new methods could be beneficial both in terms of better performance and writing more succinct code.</p>
<p>I've got a draft PR up with some initial benchmarks in the description: <a href="https://github.com/ruby/ruby/pull/10269" class="external">https://github.com/ruby/ruby/pull/10269</a>.</p> Ruby master - Feature #19628 (Open): Add ARGF.each_file for iterating file/io objectshttps://bugs.ruby-lang.org/issues/196282023-05-03T02:17:35Zdavishmcclurg (David Harsha)davishmcclurg@gmail.com
<p><code>ARGF</code> provides helpers for processing file/stdin command line arguments in various ways (bytes, chars, codepoints, etc), but it doesn't currently have a simple way to iterate through the arguments as <code>File</code>/<code>IO</code> objects. This can be useful when you want to perform an operation on the contents of an entire file (eg, JSON parsing) instead of combining them into a single string or going line-by-line. My proposal is to add an <code>ARGF.each_file</code> method that yields each file (or returns an enumerator if no block is provided).</p>
<p>Possible implementation: <a href="https://github.com/davishmcclurg/ruby/commit/cc8054c2737243f839d72622977a44fe84a95335" class="external">https://github.com/davishmcclurg/ruby/commit/cc8054c2737243f839d72622977a44fe84a95335</a></p> Ruby master - Feature #19617 (Open): Add Method#binding and UnboundMethod#binding, similar to Pro...https://bugs.ruby-lang.org/issues/196172023-04-25T19:05:52Znevans (Nicholas Evans)
<p>When a method is defined dynamically with <code>define_method</code>, it would be useful to obtain access to the defining block's binding and the local variables it has captured, based on the defining block's binding. For methods defined using the <code>def</code> keyword, the binding's local variables might be empty or might be all of the names in the method's locals table, with all values set to <code>nil</code>.</p>
<p>For UnboundMethod, it is unclear (to me) what the appropriate receiver for the binding would be, so perhaps <code>unbound.binding.receiver</code> should raise an exception.</p>
<p>Alternatively (or additionally), something like <code>Method#defining_proc</code> and <code>UnboundMethod#defining_proc</code> might be added and return <code>nil</code> for <code>def</code> definitions and the proc for <code>define_method</code> definitions.</p>
<p>This would be a useful tool when debugging from the console. As another example, it might be used to scan a code base for dynamically generated regexps which are only reachable via the enclosed local variables and test that they are all linear time (see <a href="https://github.com/ruby/net-imap/blob/92db350b24c388d2a2104f36cac9caa49a1044df/test/net/imap/regexp_collector.rb" class="external">https://github.com/ruby/net-imap/blob/92db350b24c388d2a2104f36cac9caa49a1044df/test/net/imap/regexp_collector.rb</a>).</p> Ruby master - Feature #19428 (Open): Adding a "piped heredoc" featurehttps://bugs.ruby-lang.org/issues/194282023-02-09T21:28:50Zshreeve (Steve Shreeve)steve.shreeve@gmail.com
<p>Hello,</p>
<p>I hope this is the correct place to post a small feature request.</p>
<p>HEREDOC's are awesome! There are several used within Ruby:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="o"><<</span><span class="no">END</span><span class="sh">
Have to left justify this
</span><span class="no">END</span>
<span class="o"><<-</span><span class="no">INDENTED</span><span class="sh">
Still left justified, but indented ending
</span><span class="no"> INDENTED</span>
<span class="o"><<~</span><span class="no">SQUIGGLY</span><span class="sh">
I can indent content it will be smartly "dedented/undented". Looks nicer.
</span><span class="no"> SQUIGGLY</span>
</code></pre>
<p>I love using the SQUIGGLY heredoc, which will strip off the minimum whitespace from the front of each line in the heredoc. I often do something like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">name: </span><span class="s2">"My Nice Options"</span><span class="p">,</span>
<span class="ss">description: </span><span class="o"><<~</span><span class="no">END</span><span class="sh">
This is a cool set of options.
You Can put what you like here.
</span><span class="no"> END</span>
<span class="p">}</span>
</code></pre>
<p>If you need to continue with the above, you can add a comma after like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">name: </span><span class="s2">"My Nice Options"</span><span class="p">,</span>
<span class="ss">description: </span><span class="o"><<~</span><span class="no">END</span><span class="p">,</span><span class="sh">
This is a cool set of options.
You Can put what you like here.
</span><span class="no"> END</span>
<span class="ss">details: </span><span class="o"><<~</span><span class="no">END</span><span class="p">,</span><span class="sh">
Some more stuff here...
This will only be indented 2 spaces.
And this 4 spaces.
And this 2 spaces again.
Back to the "left" side.
</span><span class="no"> END</span>
<span class="p">}</span>
</code></pre>
<p>You can even get a little squirrely and use an empty string for a heredoc terminator:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">name: </span><span class="s2">"My Nice Options"</span><span class="p">,</span>
<span class="ss">description: </span><span class="o"><<~</span><span class="no">""</span><span class="p">,</span><span class="sh">
This is a cool set of options.
You Can put what you like here.
</span><span class="no"> </span>
<span class="ss">details: </span><span class="o"><<~</span><span class="no">""</span><span class="p">,</span><span class="sh">
Some more stuff here...
This will only be indented 2 spaces.
And this 4 spaces.
And this 2 spaces again.
Back to the "left" side.
</span>
<span class="p">}</span>
</code></pre>
<p>There's one variation that I think would be nice to add, I call it a "piped heredoc". It would essentially work like the squiggly heredoc, but the "terminator" would be the next line that is not indented, and thus not "part of the heredoc".</p>
<p>Here's an example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">name: </span><span class="s2">"My Nice Options"</span><span class="p">,</span>
<span class="ss">description: </span><span class="o"><<|</span><span class="p">,</span>
<span class="no">This</span> <span class="n">is</span> <span class="n">a</span> <span class="n">cool</span> <span class="n">set</span> <span class="n">of</span> <span class="n">options</span><span class="o">.</span>
<span class="no">You</span> <span class="no">Can</span> <span class="n">put</span> <span class="n">what</span> <span class="n">you</span> <span class="n">like</span> <span class="n">here</span><span class="p">.</span>
<span class="nf">details</span><span class="p">:</span> <span class="o"><<|</span><span class="p">,</span>
<span class="no">Some</span> <span class="n">more</span> <span class="n">stuff</span> <span class="n">here</span><span class="o">...</span>
<span class="no">This</span> <span class="n">will</span> <span class="n">only</span> <span class="n">be</span> <span class="n">indented</span> <span class="mi">2</span> <span class="n">spaces</span><span class="o">.</span>
<span class="no">And</span> <span class="n">this</span> <span class="mi">4</span> <span class="n">spaces</span><span class="o">.</span>
<span class="no">And</span> <span class="n">this</span> <span class="mi">2</span> <span class="n">spaces</span> <span class="n">again</span><span class="o">.</span>
<span class="no">Back</span> <span class="n">to</span> <span class="n">the</span> <span class="s2">"left"</span> <span class="n">side</span><span class="o">.</span>
<span class="p">}</span>
</code></pre>
<p>Since the leading whitespace is used to tell when the heredoc ends, there is no need for an explicit terminator.</p>
<p>You could add one if you'd like to indicate the flavor of the content, for syntax highlighters, but it's value is ignored:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
<span class="ss">name: </span><span class="s2">"My Nice Options"</span><span class="p">,</span>
<span class="ss">description: </span><span class="o"><<|</span><span class="no">RUBY</span><span class="p">,</span>
<span class="n">users</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">user</span><span class="o">|</span>
<span class="n">user</span><span class="p">.</span><span class="nf">pay_daily_bonus!</span>
<span class="k">end</span>
<span class="ss">details: </span><span class="o"><<|</span><span class="p">,</span>
<span class="no">Some</span> <span class="n">more</span> <span class="n">stuff</span> <span class="n">here</span><span class="o">...</span>
<span class="no">This</span> <span class="n">will</span> <span class="n">only</span> <span class="n">be</span> <span class="n">indented</span> <span class="mi">2</span> <span class="n">spaces</span><span class="o">.</span>
<span class="no">And</span> <span class="n">this</span> <span class="mi">4</span> <span class="n">spaces</span><span class="o">.</span>
<span class="no">And</span> <span class="n">this</span> <span class="mi">2</span> <span class="n">spaces</span> <span class="n">again</span><span class="o">.</span>
<span class="no">Back</span> <span class="n">to</span> <span class="n">the</span> <span class="s2">"left"</span> <span class="n">side</span><span class="o">.</span>
<span class="p">}</span>
</code></pre>
<p>In the above, the "RUBY" is not really needed, but it is a hint to format that block as Ruby code.</p>
<p>This tweak to Ruby's heredocs seems like it could make Ruby syntax easy and fun to read.</p> Ruby master - Bug #19407 (Assigned): 2 threads taking from current ractor will hang foreverhttps://bugs.ruby-lang.org/issues/194072023-02-03T18:43:11Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>In the current implementation of Ractors, it's possible to <code>take</code> from the current ractor. This could be useful<br>
when co-ordinating threads:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span> <span class="c1"># do some work with obj</span>
<span class="k">end</span>
<span class="n">t0</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span> <span class="c1"># do some work with obj</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">yield</span> <span class="ss">:go</span>
</code></pre>
<p>However it hangs forever:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span>
<span class="k">end</span>
<span class="n">t0</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span>
<span class="k">end</span>
<span class="nb">sleep</span> <span class="mf">0.5</span>
</code></pre>
<p>Should "self-take" be disabled, or was it designed to allow it but this is just a bug?</p> Ruby master - Feature #19355 (Open): Add finer coarsed locking for searching callable method entrieshttps://bugs.ruby-lang.org/issues/193552023-01-19T21:04:30Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>During multi-ractor mode, unfortunately when calling methods often there's a call to the internal cruby function <code>callable_method_entry</code>, which<br>
returns a cached CME or a new one. In the case that it's cached, there's a VM lock around its access that could be reduced to a lock<br>
pertaining to the class of the caller of the method. This reduces locking in multi-ractor mode and allows, for example, object allocation to happen<br>
at the same time as method calls.</p> Ruby master - Feature #19197 (Open): Add Exception#root_causehttps://bugs.ruby-lang.org/issues/191972022-12-12T23:31:10ZAMomchilov (Alexander Momchilov)
<a name="Description"></a>
<h3 >Description<a href="#Description" class="wiki-anchor">¶</a></h3>
<p>I would like to add a <code>#root_cause</code> method to <code>Exception</code>.</p>
<p>It returns the last exception in linked-list of causality chain, that is, the original exception (whose own <code>cause</code> is <code>nil</code>).</p>
<a name="Example"></a>
<h3 >Example<a href="#Example" class="wiki-anchor">¶</a></h3>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">e</span> <span class="o">=</span> <span class="k">begin</span>
<span class="k">raise</span> <span class="s1">'A'</span> <span class="c1"># This is the root cause</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">a</span>
<span class="k">begin</span>
<span class="k">raise</span> <span class="s1">'B'</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="no">B</span>
<span class="k">begin</span>
<span class="k">raise</span> <span class="s1">'C'</span> <span class="c1"># This is the outermost cause assigned to `e`</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">c</span>
<span class="n">c</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># Here's what the structure looks like:</span>
<span class="c1"># C -> B -> A -> nil </span>
<span class="nb">p</span><span class="p">(</span><span class="n">e</span><span class="p">)</span> <span class="c1"># => #<RuntimeError: C></span>
<span class="nb">p</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="nf">cause</span><span class="p">)</span> <span class="c1"># => #<RuntimeError: B></span>
<span class="nb">p</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="nf">cause</span><span class="p">.</span><span class="nf">cause</span><span class="p">)</span> <span class="c1"># => #<RuntimeError: A></span>
<span class="nb">p</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="nf">cause</span><span class="p">.</span><span class="nf">cause</span><span class="p">.</span><span class="nf">cause</span><span class="p">)</span> <span class="c1"># => nil</span>
<span class="c1"># Here's the proposed API, showing that A is the root cause of e</span>
<span class="nb">p</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="nf">root_cause</span><span class="p">)</span> <span class="c1"># => #<RuntimeError: A></span>
<span class="c1"># And that the root_cause has no further cause</span>
<span class="nb">p</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="nf">root_cause</span><span class="p">.</span><span class="nf">cause</span><span class="p">)</span> <span class="c1"># => nil</span>
</code></pre>
<a name="Motivation"></a>
<h3 >Motivation<a href="#Motivation" class="wiki-anchor">¶</a></h3>
<p>There are some kinds of exceptions that can occur all over the place (and might be wrapped by arbitrarily many middlemen), but are attributable to a singular global cause. For example, a database outage could raise exceptions in almost every line of business logic of an app that uses ActiveRecord models.</p>
<p>Fundamentally, you wouldn't want an error report for every one of these lines. You'd want to look at the root cause, and bucket all SQL-connection issues into a single report, regardless of where they surface.</p>
<a name="Implementation"></a>
<h3 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h3>
<p>Draft PR: <a href="https://github.com/ruby/ruby/pull/6913" class="external">https://github.com/ruby/ruby/pull/6913</a></p> Ruby master - Feature #19119 (Open): Add an interface for out-of-process profiling tools to acces...https://bugs.ruby-lang.org/issues/191192022-11-10T13:31:25Zkjtsanaktsidis (KJ Tsanaktsidis)kjtsanaktsidis@gmail.com
<p>Warning: this is a very long proposal :( I don't really know what the most productive way to engage with the Ruby community about this is - if there's a better place to take this, please let me know!</p>
<p>I also want to acknowledge <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/16600">@ivoanjo (Ivo Anjo)</a> for contributing to this proposal - I bounced many ideas about profiling off him and the improved-backtrace stuff is all based on his <a href="https://github.com/ivoanjo/backtracie" class="external">backtracie</a> gem.</p>
<a name="Motivation"></a>
<h2 >Motivation<a href="#Motivation" class="wiki-anchor">¶</a></h2>
<p>When dealing with large and old Ruby apps, there is often both a need to improve the performance of some operations, as well as a lack of understanding as to how, precisely, the code works, and what aspect of it is actually slow. Furthermore, the performance issues in question often only appear in a live, production environment, where there is some traffic pattern or user data causing the problem. In situations like this, profiling tools can prove invaluable in helping to understand application performance in-situ in production.</p>
<p>The things which an engineer might use a profiler to measure include:</p>
<ul>
<li>Wall clock time; how long do particular method calls take?</li>
<li>CPU time; of the time a method takes, how long is spent actually <em>running</em> on the CPU, and how much is spent blocked waiting for e.g. a network response?</li>
<li>GVL contention; is an application using lots of threads just waiting for the GVL to become available?</li>
<li>GC time; is a particular piece of code <em>actually</em> slow, or is its slowness just a result of <em>other</em> code causing the GC to be invoked?</li>
<li>Allocations; how many objects is a particular piece of code allocating, and what impact is this having on GC?</li>
<li>Heap; of the objects a particular piece of code allocated, how many of them are still live? Is there some kind of leak?</li>
</ul>
<p>Generally, in order to collect this information from production in a minimally-impactful way, a sampling approach is used. A profiling tool periodically takes a snapshot of the current call-stack of a Ruby program; depending on what is being measured, this periodicity might be e.g. simply every N ms (for wall-clock profiling), every N allocations (for allocation profiling), etc. Then, the data will generally be combined across many instances of a program to get an aggregate view (through e.g. a flame graph).</p>
<p>In addition to this fleet-wide aggregation, it's sometimes useful to profile a particular process which has suddenly started displaying some pathology of interest. For example, if you had a webserver process that had suddenly become stuck, you might want to attach a profiler to find out <em>why</em>. In scenarios like this, it's often impossible to make some adjustment to the program to enable profiling and restart it; the act of restarting it would make the problem go away (for now!).</p>
<a name="Current-state-of-the-art"></a>
<h2 >Current state of the art<a href="#Current-state-of-the-art" class="wiki-anchor">¶</a></h2>
<p>This represents my best understanding of the ways in which most Ruby profiling tools work today. I'm sure I've missed some important details and other tools, for which I'm deeply sorry.</p>
<a name="Signal-based-profiling"></a>
<h3 >Signal-based profiling<a href="#Signal-based-profiling" class="wiki-anchor">¶</a></h3>
<p>Signal-based profilers can be used to measure CPU and wall clock time. In this scheme, a profiler (in the form of an extension gem) sets up a signal handler for SIGPROF in C, and then arranges for SIGPROF to be delivered to the process repeatedly in some kind of loop. The signal handler then captures a stack trace using the <code>rb_profile_frames</code> API from the C extension and records this as a single sample.</p>
<p>This is the mechanism used for CPU/wall clock profiling in <a href="https://github.com/tmm1/stackprof" class="external">Stackprof</a>, the <a href="https://github.com/DataDog/dd-trace-rb" class="external">Datadog continuous profiler</a>, and I'm sure others. It's also a well-known mechanism used in other non-Ruby tools like <a href="https://gperftools.github.io/gperftools/cpuprofile.html" class="external">gperftools</a></p>
<p>One benefit of this mechanism is that it should be quite fast. Triggering the signal causes a context switch into the kernel & back into the handler, but execution stays inside the current program; there's no need for the execution to switch to another program (and consequently change address space).</p>
<p>The downside of this approach is that it requires some level of cooperation from the program being profiled. Something inside the process must install the SIGPROF handler; if you have some existing, running Ruby process for which a profiler is not loaded, you cannot begin profiling it without restarting it (and using some mechanism like a <code>-rmy_profiler/autoload</code> flag).</p>
<p>Another problem with this approach is the effect these SIGPROF signals have on the application. Normally, the profiler installs the signal handler with the SA_RESTART flag; this <em>should</em> mean that any in-progress system call the application is doing when the SIGPROF arrives gets transparently restarted when the handler finishes collecting its sample. However, on Linux at least, there are some system calls which are <em>NOT</em> restarted when SA_RESTART happens - notably some network related ones like poll, epoll, and send/recv when a socket timeout is set. These system calls will instead fail with EINTR; well behaved programs and libraries <em>SHOULD</em> retry this.</p>
<p>Sadly, however, the repeated delivery of SIGPROF tens or hundreds of times per second does have a way of shaking out corner-cases in libraries where this isn't being done properly. For example, I have personally discovered the hard way that libmysqlclient version 5.7 does this wrong in one place, so enabling a SIGPROF-based profiler can cause libmysqlclient to erroneously think that database connections were closed. This is undoubtedly a bug in libmysqlclient (which, by the way, seems to be fixed in version 8), that <em>could</em> be triggered by any other signal. There's no denying though that SIGPROF-based profiling is a real torture-test for EINTR handling, and there undoubtedly <em>are</em> buggy libraries out there in the wild that people are using in their applications. It would be nice if Ruby profilers could work around this problem.</p>
<a name="RUBY_INTERNAL_EVENT_NEWOBJ-profiling"></a>
<h3 >RUBY_INTERNAL_EVENT_NEWOBJ profiling<a href="#RUBY_INTERNAL_EVENT_NEWOBJ-profiling" class="wiki-anchor">¶</a></h3>
<p>Collection of stacks from SIGPROF works for CPU/wall time profiling, but a different approach is needed for in-process profilers to collect allocation profiles. This is normally done by registering a tracepoint handler for RUBY_INTERNAL_EVENT_NEWOBJ in the profiler extension gem; this is called every time a Ruby object is allocated. From this handler, the profiler can use <code>rb_profile_frames</code> again to collect a Ruby backtrace of the code responsible for allocating this object.</p>
<a name="Ptrace-based-profiling"></a>
<h3 >Ptrace-based profiling<a href="#Ptrace-based-profiling" class="wiki-anchor">¶</a></h3>
<p>Another approach that has been used is to control the Ruby program to be profiled with another, separate process, using an appropriate platform API (e.g. ptrace on Linux). Periodically, the profiler process can use ptrace to suspend execution of the target Ruby program, and collect a stack trace of it. This is the approach used by the <a href="https://github.com/rbspy/rbspy" class="external">rbspy</a> profiler, which is itself actually a Rust program.</p>
<p>The main strength of this approach is that it allows one to begin tracing a Ruby program which is already running, <em>without restarting it</em>; rbspy can ptrace-attach to a running process and begin collecting samples straight away. This allows one to gain insight into intermittent problems once they start happening!</p>
<p>Unfortunately, "collect a stack trace" is quite tricky to do from outside the process; we want the <em>Ruby</em> level stack trace, not (or at least, as well as) the machine stack trace (which could be collected e.g. via DWARF unwinding or frame-pointer chasing). To get the Ruby stack trace requires rummaging around inside the memory of the target process (e.g. with <code>/proc/{pid}/mem</code> on Linux), to find the relevant <code>rb_control_frame_t</code> structures. Rbspy contains a huge list of structure definitions for various versions of Ruby to make this possible, but any time a new version of Ruby is released, a new version of Rbspy must also be released to account for any changes to the layout of Ruby's internal structures.</p>
<p>In theory, the ptrace approach is also worse from a performance perspective; to collect a sample, execution must switch from the process to be profiled to the profiler process, which requires switching memory mappings. Recall that with in-process SIGPROF profiling, the profiler work is done in the same process with the same memory mappings. However, this concern seems to be largely theoretical; I have not <em>actually</em> seen or heard of anybody saying that this is making rbspy too slow for their usecase.</p>
<p>Finally, although ptrace-based profiling gets us <em>close</em> to the ideal of not requiring any foresight to begin profiling a running program, there is <em>one</em> small requirement which must be satisfied ahead of time - the Ruby interpreter needs to have not had its symbols stripped so that rbspy can find the <code>ruby_current_vm_ptr</code> global. I believe rbspy makes an <em>attempt</em> to find it without the symbol but it does not claim to be reliable.</p>
<a name="Allocation-sampling-from-ptrace-based-profiling"></a>
<h3 >Allocation sampling from ptrace-based profiling<a href="#Allocation-sampling-from-ptrace-based-profiling" class="wiki-anchor">¶</a></h3>
<p>To perform allocation profiling from outside the Ruby process, we would need some analogue to RUBY_INTERNAL_EVENT_NEWOBJ. I believe this <em>could</em> be achieved by compiling Ruby with dtrace/systemtap/USDT probes enabled, and having the profiler process write a trap instruction over the top of the probe (which is how e.g. debuggers work). I don't believe rbspy or any other profiler that I found actually does this though.</p>
<a name="Perf-based-profiling"></a>
<h3 >Perf-based profiling<a href="#Perf-based-profiling" class="wiki-anchor">¶</a></h3>
<p>Linux has a dedicated subsystem called perf which (amongst many other things) can do low-overhead profiling of arbitrary processes. The sampling is done inside the kernel, so like SIGPROF (and unlike ptrace) collecting a sample requires no switch of address space. However, of course, perf only understands the machine stack, not the Ruby stack, so using perf to profile a Ruby program is not currently extraordinarily useful (unless you're profiling the Ruby VM itself or a C extension).</p>
<p>Perf actually has a <a href="https://www.brendangregg.com/perf.html#JIT_Symbols" class="external">mechanism</a> to help give meaningful stack traces for languages with JITs; the application is expected to write out a mapping of function address -> name to a file <code>/tmp/perf-$PID.map</code>; perf will use this file to symbolicate stacks. Python <a href="https://docs.python.org/dev/howto/perf_profiling.html" class="external">recently added</a> support for this mechanism as well; however, because CPython does not have a JIT, it works by generating a native trampoline for each function (with a unique address), and calling the appropriate trampolines during Python method execution to make the machine stack mirror the VM one. This mechanism is not implemented in CRuby currently.</p>
<a name="The-proposal-provide-an-external-debug-section"></a>
<h2 >The proposal: provide an "external debug section"<a href="#The-proposal-provide-an-external-debug-section" class="wiki-anchor">¶</a></h2>
<p>We ideally would like to have a way to profile Ruby applications which combines the benefits of the SIGPROF mechanism (easy, documented access to Ruby call stacks), the ptrace mechanism (the ability to attach to running processes with a minimum of foresight required), and the perf mechanism (low overhead sample collection without requiring a process address space switch). This proposal aims to provide exactly that.</p>
<p>The Ruby interpreter would have a new global variable <code>rb_debug_ext_section</code>, which is defined with <code>__attribute__((section("rb_debug_ext")))</code> so that it appeared in a separate section in the ELF binary. This variable would be constantly kept populated with up-to-date information about all the call-stacks of all threads/fibers in the program. An external debugging tool could easily ("easily") ptrace a running Ruby program, and find the address of this section in its running memory, even if symbols have been stripped. Once an external tool has found this variable, it needs to make sense of it. Ruby would provide a new header file <code>include/ruby/debug_external.h</code> which described the layout of this structure.</p>
<p>The simple, slow version of an external profiler using this interface would be a lot like rbspy; it would use ptrace to periodically stop the Ruby process, and then use the contents of <code>rb_debug_ext_section</code> to collect Ruby backtraces for CPU/wall-clock profiling. The benefit, of course, is that it's using a documented interface that can be versioned and kept backwards compatible, rather than having to constantly chase breaking changes to internal Ruby VM structures.</p>
<p>However, the benefit of this approach is that we can do better! The perf subsystem on Linux is able to invoke an eBPF program to actually collect samples (using, I think, <code>PERF_EVENT_IOC_SET_BPF</code> but I'm not 100% sure) and write them to a ring-buffer. The eBPF program can actually use the <code>debug_external.h</code> header file to figure out the current Ruby stack trace(s) itself, without needing to switch back into the profiler address space! The profiler program only needs to run periodically to empty the ring-buffer and write samples to disk.</p>
<a name="The-rider-better-stack-trace-output"></a>
<h2 >The rider: better stack trace output<a href="#The-rider-better-stack-trace-output" class="wiki-anchor">¶</a></h2>
<p>So far, we've mentioned that the profiler process will extract a stack trace out of <code>rb_debug_ext_section</code>. Let's turn our attention to what that stack trace would actually <em>be</em>.</p>
<p>Traditional profiling tools for non-dynamic languages usually work by capturing memory addresses for functions, and then deferring the translation of addresses -> names until later (possibly even on a different machine). Ruby, however, is I believe much too dynamic for a similar approach. Methods and classes can be defined and undefined dynamically over the lifetime of the program. Instruction sequences can be created and GC'd as a result of using things like <code>eval</code>. A memory address occupied by one class or iseq might later be occupied by a different one - especially because we now have GC compaction.</p>
<p>Thus, I think the only sensible thing to do is to store strings in the <code>rb_debug_ext_section</code> structure. These strings need to be valid, essentially, whilst the called method/iseq is still on the stack - there's no requirement to retain them until later. The external tool would need to copy these strings into its own process.</p>
<p>What should those actually <em>contain</em>? A traditional Ruby backtrace contains a file, line number, a method name (if available), and some other details about the iseq if present (e.g. whether it's a block or eval, whether it's , etc).</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">irb</span><span class="c1">#1(main):003:0> def foo; raise "oh no"; end;</span>
<span class="o">=></span> <span class="ss">:foo</span>
<span class="n">irb</span><span class="c1">#1(main):004:0> foo</span>
<span class="p">(</span><span class="n">irb</span><span class="c1">#1):3:in `foo': oh no (RuntimeError)</span>
<span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="c1">#1):4:in `<main>'</span>
</code></pre>
<p>I do not believe this is the most useful way to present this information from a profiling perspective, however. When dealing with a large monolithic application, profiles will be collected process-wide and aggregated on some kind of central dashboard; there could be many methods called the same thing (think <code>def create</code> in a Rails controller, for example). The filename can help disambiguate in circumstances like this, but C functions don't even <em>have</em> a filename, so just print the filename of the thing that called them:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">irb</span><span class="c1">#1(main):005:0> 1.times { raise "oh no" }</span>
<span class="p">(</span><span class="n">irb</span><span class="c1">#1):5:in `block in <main>': oh no (RuntimeError)</span>
<span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="c1">#1):5:in `times' # I did not define Integer#times in IRB!</span>
<span class="n">from</span> <span class="p">(</span><span class="n">irb</span><span class="c1">#1):5:in `<main>'</span>
</code></pre>
<p>All of this can be generally figured out by looking at the code, but often when we're looking at e.g. a profiling dashboard, having to keep looking between the flame graph and the code can be rather annoying.</p>
<p>It would be nice if instead, our profiles contained the name of the class on which a method is defined; something like <code>FooClass#the_method</code>. Ruby has a method <code>rb_profile_frame_qualified_method_name</code> which can give useful output like this in many cases. However, in many common cases like e.g. anonymous classes, it will present the name of the class as something like "#<a href="Class:0x0000000000db48e0" class="external">Class:0x0000000000db48e0</a>". This is worse than useless for profiling; that address will be different amongst different processes being profiled, so multiple profiles can't be aggregated together. In fact, that address isn't even guaranteed to be constant within the same process anymore, because of compaction.</p>
<p>I would propose that we have a new way of naming methods which produces useful strings in all cases, without any addresses in them. The rules I have come up with so far are:</p>
<ul>
<li>
<code>"#<refinement Foo of Bar>"</code> for a refinement module adding methods to<br>
Bar</li>
<li>
<code>"#<instance of Foo>"</code> for a particular instance of Foo</li>
<li>
<code>"#<singleton of Foo>"</code> for Foo's singleton class.</li>
<li>
<code>"#<anonymous subclass of Foo>"</code> for an anonymous subclass</li>
<li>The usual classpath string otherwise</li>
</ul>
<p>Note that nesting is OK too - so a method defined on the singleton class of a particular Foo object would be "#<singleton of #>#the_method".</p>
<p>So, my proposal is that this is the format of the method name that appears in the <code>rb_debug_ext_section</code> structure.</p>
<a name="Where-have-I-got-to-so-far"></a>
<h2 >Where have I got to so far?<a href="#Where-have-I-got-to-so-far" class="wiki-anchor">¶</a></h2>
<p>OK, so I have a draft PR up which should hopefully help make some of this clearer: <a href="https://github.com/ruby/ruby/pull/6706" class="external">https://github.com/ruby/ruby/pull/6706</a>. It is of course in no way even close to merge ready, but I'm hoping it helps illustrate some of my ideas here:</p>
<ul>
<li>
<a href="https://github.com/ruby/ruby/pull/6706/files#diff-661f9269009ec827185eafa5ee05bd7251bbe0a55dec361c9c5c25bb2a43a098" class="external">The debug_external.h file</a> that defines the externally-visible structures</li>
<li>Where threads are <a href="https://github.com/ruby/ruby/pull/6706/files#diff-aa2addb929749a4a0330b93ceecec5bc5485751a362524f5cb37bf22dff1936eR65" class="external">added</a> and <a href="https://github.com/ruby/ruby/pull/6706/files#diff-aa2addb929749a4a0330b93ceecec5bc5485751a362524f5cb37bf22dff1936eR110" class="external">removed</a> from the <code>rb_debug_ext_section</code> structure</li>
<li>Where frames are <a href="https://github.com/ruby/ruby/pull/6706/files#diff-f8c174347e6ea8889b5036064a1ff4fe5e7c53a821befa9bdc5ccbf17800a649R407" class="external">pushed</a> and <a href="https://github.com/ruby/ruby/pull/6706/files#diff-f8c174347e6ea8889b5036064a1ff4fe5e7c53a821befa9bdc5ccbf17800a649R437" class="external">popped</a> from the <code>rb_debug_ext_section</code> structure</li>
<li>The <a href="https://github.com/ruby/ruby/pull/6706/files#diff-89a67a4d5b348ac6f9cabe56d2847545be67809b01d856b3541e96471014bd99R573" class="external">tests</a> illustrate what the new qualified method name output looks like.</li>
</ul>
<a name="What-do-I-want-feedback-on"></a>
<h2 >What do I want feedback on?<a href="#What-do-I-want-feedback-on" class="wiki-anchor">¶</a></h2>
<p>This whole project is obviously still about 20% cooked, so, anything and everything. But more specifically, these are the questions I would really like some help with :)</p>
<ul>
<li>Does this <em>approach</em> seem sensible? Is the basic <em>idea</em> of "expose some documented data structure to other processes that are able to read my memory" a sound one?</li>
<li>What should I do with the qualified-method-name-without-addresses work? At the moment I exposed that logic behind new methods <code>Method#debug_name</code> and <code>Thread::Backtrace::External#debug_label</code>. Is there some appetite to open a proposal to have that in CRuby?</li>
<li>Should we even consider <em>changing the default output</em> of thread backtraces to print these qualified names?</li>
<li>There are some 'infrastructural' commits on that branch of mine - one to <a href="https://github.com/ruby/ruby/pull/6706/commits/f446f5281f58e8761d1826b6b1c4a98facd0472e" class="external">find some extra space in <code>rb_method_entry_t</code></a> and one to <a>add some new atomic helpers</a>. Is this the sort of thing that would make sense to try and land now or only when this is all closer to done?</li>
<li>I haven't yet actually implemented anything to try and <em>read</em> this external debug section. Should it be
<ol>
<li>some external repo, in a non-Ruby language e.g. Rust or something?</li>
<li>A Ruby gem, with a C extension to handle all the ptrace/bpf'y bits?</li>
<li>The gem, but inside the CRuby source tree?<br>
I'm leaning towards 2, but not really sure.</li>
</ol>
</li>
</ul>
<p>Thank you, to anybody who actually got to the bottom of this wall of text, and thanks doubly to anybody who provides feedback!</p> Ruby master - Feature #18835 (Open): Add InstructionSequence#type methodhttps://bugs.ruby-lang.org/issues/188352022-06-16T22:30:35Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>This method returns a symbol representing the type of the instruction<br>
sequence object.</p>
<p>I'm trying to collect some statistics about instruction sequences for an entire system, but I mostly care about methods and blocks. This feature lets me select only methods and blocks to analyze.</p>
<p>I am using a script like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">walk</span> <span class="n">iseq</span>
<span class="k">case</span> <span class="n">iseq</span><span class="p">.</span><span class="nf">type</span>
<span class="k">when</span> <span class="ss">:METHOD</span><span class="p">,</span> <span class="ss">:BLOCK</span>
<span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">sends</span> <span class="o">=</span> <span class="mi">0</span>
<span class="n">iseq</span><span class="p">.</span><span class="nf">to_a</span><span class="p">.</span><span class="nf">last</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">insn</span><span class="o">|</span>
<span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">insn</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Array</span><span class="p">)</span>
<span class="k">case</span> <span class="n">insn</span>
<span class="k">in</span> <span class="p">[</span><span class="ss">:opt_send_without_block</span><span class="p">,</span> <span class="n">_</span><span class="p">]</span>
<span class="n">sends</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">in</span> <span class="p">[</span><span class="ss">:send</span><span class="p">,</span> <span class="n">_</span><span class="p">]</span>
<span class="n">sends</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">in</span> <span class="p">[</span><span class="ss">:invokeblock</span><span class="p">]</span>
<span class="n">sends</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">else</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="p">[</span><span class="n">count</span><span class="p">,</span> <span class="n">sends</span><span class="p">]</span>
<span class="k">end</span>
<span class="n">iseq</span><span class="p">.</span><span class="nf">each_child</span> <span class="p">{</span> <span class="o">|</span><span class="n">n</span><span class="o">|</span> <span class="n">walk</span><span class="p">(</span><span class="n">n</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
<span class="n">iseq</span> <span class="o">=</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">InstructionSequence</span><span class="p">.</span><span class="nf">compile_file</span><span class="p">(</span><span class="no">ARGV</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="n">walk</span> <span class="n">iseq</span>
</code></pre>
<p>Then in my shell I can do this:</p>
<pre><code>$ find ~/git/rails/activerecord/lib -name '*.rb' -exec ./miniruby test.rb {} \;
</code></pre>
<p>I'm able to calculate instructions per method as well as number of "sends" per iseq. (Of course this isn't 100% accurate because of metaprogramming etc, but I think it lets us get good estimates)</p>
<p>I made a pull request <a href="https://github.com/ruby/ruby/pull/5809" class="external">here</a> and I've attached a patch as well.</p> Ruby master - Feature #18762 (Open): Add an Array#undigits that compliments Integer#digitshttps://bugs.ruby-lang.org/issues/187622022-05-02T22:47:02Zshan (Shannon Skipper)
<p>I've found Integer#digits convenient and useful but several times have needed to go from the place-value notation back to an Integer after manipulation and wished there was a complimentary Array#undigits.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Array</span>
<span class="k">def</span> <span class="nf">undigits</span><span class="p">(</span><span class="n">base</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span>
<span class="n">each_with_index</span><span class="p">.</span><span class="nf">sum</span> <span class="k">do</span> <span class="o">|</span><span class="n">digit</span><span class="p">,</span> <span class="n">exponent</span><span class="o">|</span>
<span class="n">digit</span> <span class="o">*</span> <span class="n">base</span><span class="o">**</span><span class="n">exponent</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="mi">42</span><span class="p">.</span><span class="nf">digits</span><span class="p">.</span><span class="nf">undigits</span>
<span class="c1">#=> 42</span>
<span class="mi">42</span><span class="p">.</span><span class="nf">digits</span><span class="p">(</span><span class="mi">16</span><span class="p">).</span><span class="nf">undigits</span><span class="p">(</span><span class="mi">16</span><span class="p">)</span>
<span class="c1">#=> 42</span>
</code></pre>
<p>Below is my stab at a Ruby implementation with behavior mirroring Integer#digits.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Array</span>
<span class="k">def</span> <span class="nf">undigits</span><span class="p">(</span><span class="n">base</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span>
<span class="n">base_int</span> <span class="o">=</span> <span class="n">base</span><span class="p">.</span><span class="nf">to_int</span>
<span class="k">raise</span> <span class="no">TypeError</span><span class="p">,</span> <span class="s2">"wrong argument type </span><span class="si">#{</span><span class="n">base_int</span><span class="p">.</span><span class="nf">class</span><span class="si">}</span><span class="s2"> (expected Integer)"</span> <span class="k">unless</span> <span class="n">base_int</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Integer</span><span class="p">)</span>
<span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">,</span> <span class="s1">'negative radix'</span> <span class="k">if</span> <span class="n">base_int</span><span class="p">.</span><span class="nf">negative?</span>
<span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">,</span> <span class="s2">"invalid radix </span><span class="si">#{</span><span class="n">base_int</span><span class="si">}</span><span class="s2">"</span> <span class="k">if</span> <span class="n">base_int</span> <span class="o"><</span> <span class="mi">2</span>
<span class="n">each_with_index</span><span class="p">.</span><span class="nf">sum</span> <span class="k">do</span> <span class="o">|</span><span class="n">digit</span><span class="p">,</span> <span class="n">exponent</span><span class="o">|</span>
<span class="k">raise</span> <span class="no">MathDomainError</span><span class="p">,</span> <span class="s1">'out of domain'</span> <span class="k">if</span> <span class="n">digit</span><span class="p">.</span><span class="nf">negative?</span>
<span class="n">digit</span> <span class="o">*</span> <span class="n">base_int</span><span class="o">**</span><span class="n">exponent</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre> Ruby master - Feature #18594 (Open): Add a #to_h method on URI::Generichttps://bugs.ruby-lang.org/issues/185942022-02-21T07:30:49Zjimcavoli (Jim Cavoli)
<p>It's just surprisingly challenging to get a hash representation of a parsed URI where the keys are the component names and the values are the component values.</p>
<p>The shortest form I could come up with using only public methods on <code>URI::Generic</code> is rather clumsy-feeling:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">uri</span> <span class="o">=</span> <span class="o">::</span><span class="no">URI</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="n">hsh</span> <span class="o">=</span> <span class="p">[</span><span class="n">uri</span><span class="p">.</span><span class="nf">component</span><span class="p">,</span> <span class="n">uri</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="o">*</span><span class="n">uri</span><span class="p">.</span><span class="nf">component</span><span class="p">)].</span><span class="nf">transpose</span><span class="p">.</span><span class="nf">to_h</span>
</code></pre>
<p>Hence this suggested patch:</p>
<pre><code>diff --git a/lib/uri/generic.rb b/lib/uri/generic.rb
index cfa0de6b74..f27a07a53c 100644
--- a/lib/uri/generic.rb
+++ b/lib/uri/generic.rb
@@ -1367,6 +1367,13 @@ def to_s
str
end
+ #
+ # Returns a Hash representing the URI components
+ #
+ def to_h
+ [component, component_ary].transpose.to_h
+ end
+
#
# Compares two URIs.
#
</code></pre>
<p>Which would allow the much more ergonomic, idiomatic and terse usage:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">uri</span> <span class="o">=</span> <span class="o">::</span><span class="no">URI</span><span class="p">.</span><span class="nf">parse</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="n">hsh</span> <span class="o">=</span> <span class="n">uri</span><span class="p">.</span><span class="nf">to_h</span>
</code></pre>
<p>Also happy to put together tests/specs for that as required.</p> Ruby master - Feature #18593 (Open): Add back URI.escapehttps://bugs.ruby-lang.org/issues/185932022-02-18T19:33:31Zkallisti5 (Alexander von Gluck)kallisti5@unixzen.com
<p>It seems like there should have been a compatibility call left in place for the removal of URI escape between stdlib 2.x and 3.x</p>
<p>As seen here:<br>
<a href="https://github.com/qoobaa/s3/issues/132" class="external">https://github.com/qoobaa/s3/issues/132</a></p>
<p>Various projects are breaking due to the move of escape to DEFAULT_PARSER</p>
<pre><code>--- /home/kallisti5/.gem/ruby/3.0.0/gems/s3-0.3.29/lib/s3/bucket.rb.original 2022-02-18 13:26:37.247078560 -0600
+++ /home/kallisti5/.gem/ruby/3.0.0/gems/s3-0.3.29/lib/s3/bucket.rb 2022-02-18 13:26:47.707146732 -0600
@@ -151,7 +151,7 @@
# If there are more than 1000 objects S3 truncates listing and
# we need to request another listing for the remaining objects.
while parse_is_truncated(response.body)
- next_request_options = {:marker => URI.escape(objects_attributes.last[:key])}
+ next_request_options = {:marker => URI::DEFAULT_PARSER.escape(objects_attributes.last[:key])}
if max_keys
break if objects_attributes.length >= max_keys
</code></pre> Ruby master - Feature #18332 (Open): a ? bhttps://bugs.ruby-lang.org/issues/183322021-11-13T18:41:51Zdorianmariefr (Dorian Marié)
<p>It would be a shortcut for <code>a ? b : nil</code>:</p>
<p>e.g.</p>
<pre><code>"#{current_path == "/" ? "font-bold"}"
"#{user.admin? ? "text-red-600"}"
</code></pre>
<p>Doing <code>a && b</code> returns <code>false</code> which converted to a string gives <code>"false"</code>.</p>
<p>When <code>nil</code> converts to a string it gives <code>""</code>.</p>
<p>I would use it mostly in string interpolations.</p> Ruby master - Feature #18275 (Assigned): Add an option to define_method to not capture the surrou...https://bugs.ruby-lang.org/issues/182752021-10-27T19:27:45Zvinistock (Vinicius Stock)
<p>Invoking <code>define_method</code> will capture the surrounding environment, making sure we have access to anything defined in that surrounding scope. However, that’s not always necessary. There are uses for <code>define_method</code> where the surrounding environment is not needed.</p>
<p>Always capturing the surrounding environment slows down even the methods that don’t need access to it. Additionally, it prevents methods created using <code>define_method</code> to exist in all Ractors in a program.</p>
<p>If we could add an option to disable capturing the surrounding environment for <code>define_method</code>, we could make it so that it creates the dynamic method in all Ractors.</p>
<p>There could also be some performance benefits for the usages that do not need the surrounding environment. By not having to keep references to the surrounding scope, the GC could let go of locals from that environment, which might benefit GC as well.</p>
<p>Another option could be to accept the list of locals that the <code>define_method</code> invocation will need, as a way of letting go of references that are no longer needed.</p>
<p>Examples:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Current behavior</span>
<span class="c1">#</span>
<span class="c1"># All of the surrounding environment is captured and references are kept for the locals</span>
<span class="c1"># The method created only exists in the current Ractor, due to possible references to the captured variables</span>
<span class="n">some_random_thing</span> <span class="o">=</span> <span class="s2">"a"</span> <span class="o">*</span> <span class="mi">10000</span>
<span class="n">some_captured_block</span> <span class="o">=</span> <span class="o">-></span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span>
<span class="n">define_method</span><span class="p">(</span><span class="ss">:my_method</span><span class="p">,</span> <span class="o">&</span><span class="n">some_captured_block</span><span class="p">)</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Enable/disable all option</span>
<span class="c1">#</span>
<span class="c1"># Add an option that allows disabling capturing the surrounding environment completely</span>
<span class="c1"># The method created exists in all Ractors and none of the references are kept</span>
<span class="n">some_random_thing</span> <span class="o">=</span> <span class="s2">"a"</span> <span class="o">*</span> <span class="mi">10000</span>
<span class="n">some_captured_block</span> <span class="o">=</span> <span class="o">-></span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span>
<span class="n">define_method</span><span class="p">(</span><span class="ss">:my_method</span><span class="p">,</span> <span class="ss">capture_environment: </span><span class="kp">false</span><span class="p">,</span> <span class="o">&</span><span class="n">some_captured_block</span><span class="p">)</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Choose variables option</span>
<span class="c1">#</span>
<span class="c1"># Add an option that allows indicating which locals are needed for a define_method invocation</span>
<span class="c1"># The method created exists in all Ractors if no locals are needed</span>
<span class="c1"># The method is created only in the current Ractor if at least one local is needed</span>
<span class="c1"># All “unneeded” locals are let go</span>
<span class="n">some_random_thing</span> <span class="o">=</span> <span class="s2">"a"</span> <span class="o">*</span> <span class="mi">10000</span> <span class="c1"># kept because `my_method` needs it</span>
<span class="n">another_random_thing</span> <span class="o">=</span> <span class="s2">"b"</span> <span class="o">*</span> <span class="mi">10000</span> <span class="c1"># not kept</span>
<span class="n">some_captured_block</span> <span class="o">=</span> <span class="o">-></span> <span class="p">{</span> <span class="o">...</span> <span class="p">}</span>
<span class="n">define_method</span><span class="p">(</span><span class="ss">:my_method</span><span class="p">,</span> <span class="ss">needs: </span><span class="p">[</span><span class="ss">:some_random_thing</span><span class="p">],</span> <span class="o">&</span><span class="n">some_captured_block</span><span class="p">)</span>
</code></pre> Ruby master - Misc #18248 (Open): Add Feature Triaging Guidehttps://bugs.ruby-lang.org/issues/182482021-10-11T16:14:14Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<p>Ruby added a bug triaging guide in June 2019, and since then I've used it to reduce the number of open bugs in the tracker from over 1400 to about 300. Ruby currently has over 1200 open feature requests on the issue tracker. From a cursory review, many of these have already been implemented, and many are unlikely to be desired. I would like to add a feature triaging guide to Ruby and start triaging feature requests, with the goal of having open feature requests be features not yet implemented that the Ruby core team would like implemented or would consider patches for. By doing so, we can make it easier for potential contributors to Ruby to easily see possible contributions they could make.</p>
<p>I've added a pull request with a draft of the proposed guide: <a href="https://github.com/ruby/ruby/pull/4953" class="external">https://github.com/ruby/ruby/pull/4953</a></p> Ruby master - Feature #18228 (Open): Add a `timeout` option to `IO.copy_stream`https://bugs.ruby-lang.org/issues/182282021-09-27T12:16:09Zbyroot (Jean Boussier)byroot@ruby-lang.org
<a name="Context"></a>
<h3 >Context<a href="#Context" class="wiki-anchor">¶</a></h3>
<p>In many situations dealing with large files, <code>IO.copy_stream</code> when usable bring major performance gains (often twice faster at the very least). And more importantly, when the copying is deferred to the kernel, the performance is much more consistent as it is less impacted by the CPU utilization on the machine.</p>
<p>However, it is often unsafe to use because it doesn't have a timeout, so you can only use it if both the source and destination IOs are trusted, otherwise it is trivial for an attacker to DOS the service by reading the response very slowly.</p>
<a name="Some-examples"></a>
<h3 >Some examples<a href="#Some-examples" class="wiki-anchor">¶</a></h3>
<ul>
<li>It is <a href="https://github.com/ruby/webrick/commit/54be684da9d993ad6c237e2e9853eb98bcbaae6e" class="external">used by <code>webrick</code></a>.</li>
<li>
<code>Net::HTTP</code> uses it to send request body if they are IOs, but <a href="https://github.com/ruby/net-http/pull/27" class="external">it is used with a "fake IO" to allow for timeouts</a>, so <code>sendfile(2)</code> &co are never used.</li>
<li>
<a href="https://github.com/puma/puma/pull/2703" class="external">A proof of concept of integrating in puma shows a 2x speedup</a>.</li>
<li>
<a href="https://github.com/nahi/httpclient/pull/383" class="external">Various other HTTP client could use it as well</a>.</li>
<li>I used it in private projects to download and upload large archives in and out of Google Cloud Storage with great effects.</li>
</ul>
<a name="Possible-implementation"></a>
<h3 >Possible implementation<a href="#Possible-implementation" class="wiki-anchor">¶</a></h3>
<p>The main difficulty is that the underlying sycalls don't have a timeout either.</p>
<p>The main syscall used in these scenarios is <code>sendfile(2)</code>. It doesn't have a timeout parameter, however if called on file descriptors with <code>O_NONBLOCK</code> it does return early and allow for a <code>select/poll</code> loop. I did a very quick and dirty experiment with this, and it does seem to work.</p>
<p>The other two accelerating syscalls are <a href="https://man7.org/linux/man-pages/man2/copy_file_range.2.html" class="external"><code>copy_file_range(2)</code></a> (linux) and <a href="https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fcopyfile.3.html" class="external"><code>fcopyfile(2)</code></a> (macOS). Neither have a timeout, and neither manpage document an <code>EAGAIN / EWOULDBLOCK</code> error. However these syscalls are limited to real file copies, generally speaking timeouts for real files are less of a critical need, so it would be possible to simply not use these syscalls if a timeout is provided.</p>
<a name="Interface"></a>
<h3 >Interface<a href="#Interface" class="wiki-anchor">¶</a></h3>
<p><code>copy_stream(src, dst, copy_length, src_offset, timeout)</code><br>
or <code>copy_stream(src, dst, copy_length, src_offset, timeout: nil)</code></p>
<p>As for the return value in case of a timeout, it is important to convey both that a timeout happened, and the number of bytes that were copied, otherwise it makes retries impossible.</p>
<ul>
<li>It could simply returns the number of byte, and let the caller compare it to the expected number of bytes copied, but that wouldn't work in cases where the size of <code>src</code> isn't known.</li>
<li>It could return <code>-1 - bytes_copied</code>, not particularly elegant but would work.</li>
<li>It could return multiple values or some kind of result object when a timeout is provided.</li>
<li>It could raise an error, with <code>bytes_copied</code> as an attribute on the error.</li>
</ul>
<p>Or alternatively <code>copy_stream</code> would be left without a timeout, and some kind of <code>copy_stream2</code> would be introduced so that <code>copy_stream</code> return value wouldn't be made inconsistent.</p> Ruby master - Feature #18179 (Open): Add Math methods to Numerichttps://bugs.ruby-lang.org/issues/181792021-09-20T04:09:13Zankane (Andrew Kane)
<p>Hi, I wanted to get thoughts on adding class methods from <code>Math</code> as instance methods on <code>Numeric</code>.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">x</span><span class="p">.</span><span class="nf">sqrt</span> <span class="c1"># vs Math.sqrt(x)</span>
<span class="n">x</span><span class="p">.</span><span class="nf">log</span> <span class="c1"># vs Math.log(x)</span>
</code></pre>
<p>Rust takes this approach and it (subjectively) feels more intuitive/object-oriented. It also seems more consistent with methods like <code>x.abs</code>.</p> Ruby master - Feature #18168 (Open): Add ActiveSupport deep_transform_values to Rubyhttps://bugs.ruby-lang.org/issues/181682021-09-15T05:29:44Zmaximus242 (Philip Solobay)
<p>I think since transform_values is a part of Ruby, it makes sense to support the nested version of transform values</p> Ruby master - Feature #18146 (Open): Add `delete_prefix` and `delete_suffix` to `Pathname`https://bugs.ruby-lang.org/issues/181462021-09-03T04:59:47Zkoic (Koichi ITO)koic.ito@gmail.com
<p><code>Pathname</code> has <code>sub</code> method, but does not have the methods mentioned in the title.<br>
<code>Pathname</code> may be able to provide <code>delete_prefix</code> and <code>delete_suffix</code> like <code>String#delete_prefix</code> and <code>String#delete_suffix</code> added in Ruby 2.5</p>
<p>This is an idea I got from feedback on RuboCop Performance.<br>
<a href="https://github.com/rubocop/rubocop-performance/issues/245" class="external">https://github.com/rubocop/rubocop-performance/issues/245</a></p>
<p>Thank you.</p> Ruby master - Feature #18004 (Open): Add Async to the stdlibhttps://bugs.ruby-lang.org/issues/180042021-06-22T18:29:26Zshan (Shannon Skipper)
<p>Adding Async to the stdlib would signal a clear concurrency story for Ruby 3 to compliment Ractor-based parallelism. I don't know how ioquatix feels about adding Async to stdlib, but I wanted to propose it since we keep getting questions about concurrent I/O with Ruby 3 in the community.</p>
<p>Ractors get a fair amount of attention on the #ruby IRC channels and Ruby Discord. When Ractors are discussed, question around concurrent I/O in Ruby 3 often follow. Folk don't seem to be aware of Async, so we often cite the Ruby 3 release notes Async Net::HTTP example shown below.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'async'</span>
<span class="nb">require</span> <span class="s1">'net/http'</span>
<span class="nb">require</span> <span class="s1">'uri'</span>
<span class="no">Async</span> <span class="k">do</span>
<span class="p">[</span><span class="s2">"ruby"</span><span class="p">,</span> <span class="s2">"rails"</span><span class="p">,</span> <span class="s2">"async"</span><span class="p">].</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">topic</span><span class="o">|</span>
<span class="no">Async</span> <span class="k">do</span>
<span class="no">Net</span><span class="o">::</span><span class="no">HTTP</span><span class="p">.</span><span class="nf">get</span><span class="p">(</span><span class="no">URI</span> <span class="s2">"https://www.google.com/search?q=</span><span class="si">#{</span><span class="n">topic</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>The main downside I see for this proposal is the bloat from Async's several gem dependencies. For what it's worth, nio4r has been a staple for a long time and is also the only dependency of Puma.</p>
<pre><code>Async is a composable asynchronous I/O framework for Ruby based on nio4r and timers.
</code></pre>
<p>Async is just so useful it would be awesome to add to the stdlib. It fills and important gap for concurrent I/O with Ruby 3 and would be exciting to see included in a future release.</p>
<p>See <a href="https://github.com/socketry/async#readme" class="external">https://github.com/socketry/async#readme</a></p> Ruby master - Feature #17942 (Open): Add a `initialize(public @a, private @b)` shortcut syntax fo...https://bugs.ruby-lang.org/issues/179422021-06-09T04:55:04ZTylerRick (Tyler Rick)tyler@tylerrick.com
<p>This proposal builds on the proposed <code>initialize(@a, @b)</code> instance var assignment shortcut syntax described in <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: Introduce a new "shortcut assigning" syntax to convenient setup instance variables (Assigned)" href="https://bugs.ruby-lang.org/issues/15192">#15192</a>.</p>
<ol>
<li>It allows you to add an <em>optional</em> <code>public</code>/<code>protected</code>/<code>private</code> modifier before any instance var parameter. Doing so automatically defines <em>accessor methods</em> (with the given access modifier; equivalent to <code>attr_accessor</code> inside of a <code>public</code>/<code>protected</code>/<code>private</code> block) for the instance var it precedes.</li>
<li>If the visibility modifier is omitted, then it defaults to automatically <em>no</em> getter/setter methods for that instance var (it <em>only</em> does an assignment of that already-private instance var).</li>
</ol>
<a name="Parameter-properties-in-TypeScript-language"></a>
<h2 >Parameter properties in TypeScript language<a href="#Parameter-properties-in-TypeScript-language" class="wiki-anchor">¶</a></h2>
<p>This is inspired by TypeScript's <code>constructor(public a, private b)</code> syntax, which allows you to write this (<a href="https://www.typescriptlang.org/play?#code/MYGwhgzhAEBiD29oG8BQ0PWPAdhALgE4Cuw+8hAFAA7EBGIAlsNGAFw7EC2dApoQBpotBs2h0O3PoOGFGANzD5eWST34BKFOkwBfVPqA" class="external">REPL</a>):</p>
<pre><code class="js syntaxhl" data-language="js"><span class="kd">class</span> <span class="nc">Foo</span> <span class="p">{</span>
<span class="nf">constructor</span><span class="p">(</span><span class="kr">public</span> <span class="nx">a</span><span class="p">:</span><span class="nx">number</span><span class="p">,</span> <span class="kr">public</span> <span class="nx">b</span><span class="p">:</span><span class="nx">number</span><span class="p">,</span> <span class="kr">private</span> <span class="nx">c</span><span class="p">:</span><span class="nx">number</span><span class="p">)</span> <span class="p">{</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>instead of this:</p>
<pre><code class="js syntaxhl" data-language="js"><span class="kd">class</span> <span class="nc">Foo</span> <span class="p">{</span>
<span class="nf">constructor</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">,</span> <span class="nx">c</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">a</span> <span class="o">=</span> <span class="nx">a</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">b</span> <span class="o">=</span> <span class="nx">b</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">c</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre>
<p>(The <code>public</code>/<code>private</code> access modifiers actually disappear in the transpiled JavaScript code because it's only the TypeScript compiler that enforces those access modifiers, and it does so at <em>compile</em> time rather than at run time.)</p>
<p>Further reading:</p>
<ul>
<li><a href="https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties" class="external">https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties</a></li>
<li><a href="https://basarat.gitbook.io/typescript/future-javascript/classes#define-using-constructor" class="external">https://basarat.gitbook.io/typescript/future-javascript/classes#define-using-constructor</a></li>
<li><a href="https://kendaleiv.com/typescript-constructor-assignment-public-and-private-keywords/" class="external">https://kendaleiv.com/typescript-constructor-assignment-public-and-private-keywords/</a></li>
</ul>
<a name="Differences-from-TypeScript"></a>
<h2 >Differences from TypeScript<a href="#Differences-from-TypeScript" class="wiki-anchor">¶</a></h2>
<p>I propose adding a similar feature to Ruby, but with following differences from TypeScript:</p>
<ol>
<li>
<p>Use <strong><code>@a</code></strong> instead of bare <code>a</code>. This makes it <em>much</em> clearer that you are assigning directly to instance variables instead of to locals.</p>
<ul>
<li>Rationale: The <code>@</code> is actually <em>part</em> of the instance variable name, and is inseparable from it. (This is also consistent with how the <code>#</code> is part of the name itself in JavaScript's <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields#private_instance_fields" class="external">(Private instance fields)</a>.)</li>
<li>(<code>public a</code> would be a syntax error because there's no such thing as access modifiers for locals. Okay, I guess there's no such thing as access modifiers for instance vars either, which is why...)</li>
</ul>
</li>
<li>
<p>Make the syntax for <em><strong>assigning</strong></em> to instance vars (<code>@a</code>) (the proposal in <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: Introduce a new "shortcut assigning" syntax to convenient setup instance variables (Assigned)" href="https://bugs.ruby-lang.org/issues/15192">#15192</a>) and defining <em><strong>accessor methods</strong></em> for those instance vars (<code>public</code>/<code>private</code>) separate/distinct.</p>
<ul>
<li>In other words, rather than make the <code>public</code>/<code>private</code> keywords a <em>required</em> part of the syntax like it is for TypeScript <a href="https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties" class="external">parameter properties</a>, you could omit the modifier and it would still do the instance var _assignment*.</li>
<li>The <code>public</code>/<code>private</code> access modifiers be an additional (<em>optional</em>) shortcut when you want to add an <em><strong>accessor method</strong></em> in <em>addition</em> to doing an <em><strong>assignment</strong></em> .</li>
<li>Unlike Java and TypeScript where you <em>can</em> add access modifiers to instance variables, in Ruby, <code>public</code>/<code>private</code> <em>can't</em> be applied to instance variables (direct access is only possible from within the instance). So if we're going to allow a <code>public</code>/<code>private</code> modifier here at all, They <em>must</em> refer to methods, specifically accessor methods for those instance variables.</li>
</ul>
</li>
<li>
<p>Keep it <strong>private</strong> by default (which of course <code>@a</code> by itself implies—it <em>is</em> private unless you add a public accessor).</p>
<ul>
<li>(Rather than make it <code>public</code> by default like it is in TypeScript.)</li>
<li>Keeping instance variables completely private is probably what people will want most of the time, and we should optimize the ergonomics for the most common case.</li>
<li>Private is a safer default, and should be assumed unless you explicitly ask for a public accessor to be added.</li>
<li>I bet TypeScript made the <code>public</code> the default mostly to be consistent with JavaScript (which TypeScript compiles to): JavaScript (along with other languages like Java) allows direct access (no getter/setter neede) to instance properties/variables from objects outside the instance. JavaScript doesn't even <em>have</em> a way to make instance variables private (but hopefully will soon with this <a href="https://github.com/tc39/proposal-private-methods" class="external">proposal</a> to add <code>#a</code> syntax for private properties).</li>
</ul>
</li>
</ol>
<p>So this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Thing</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="kp">public</span> <span class="vi">@a</span><span class="p">,</span> <span class="kp">public</span> <span class="vi">@b</span><span class="p">,</span> <span class="vi">@c</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>would be equivalent to this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Thing</span>
<span class="nb">attr_accessor</span> <span class="ss">:a</span><span class="p">,</span> <span class="ss">:b</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">)</span>
<span class="vi">@a</span> <span class="o">=</span> <span class="n">a</span>
<span class="vi">@b</span> <span class="o">=</span> <span class="n">b</span>
<span class="vi">@c</span> <span class="o">=</span> <span class="n">c</span>
<span class="k">end</span>
</code></pre>
<a name="How-is-initializeprivate-a-different-from-initializea"></a>
<h2 >How is <code>initialize(private @a)</code> different from <code>initialize(@a)</code>?<a href="#How-is-initializeprivate-a-different-from-initializea" class="wiki-anchor">¶</a></h2>
<p>Even though <code>@a</code> by itself is already private...</p>
<ol>
<li>This defines a private accessor for that instance var, which lets you write <code>self.a =</code> instead of <code>@a =</code> (if you want).</li>
<li>Having a concise way to do that is helpful, for example if you want to make it a matter of practice/policy to only set an instance variable by going through its <em>setter method</em>. (See <a href="https://stackoverflow.com/questions/25571642/ruby-private-and-public-accessors" class="external">discussion here</a>.)</li>
</ol>
<p>Why not just use <code>initialize(private @a)</code> to be consistent with TypeScript spec?</p>
<ul>
<li>TypeScript's <code>public</code>/<code>private</code> is not standard JavaScript. In fact, if the <a href="https://github.com/tc39/proposal-private-methods" class="external">private methods/fields proposal</a> had existed when TypeScript added <a href="https://www.typescriptlang.org/docs/handbook/2/classes.html#parameter-properties" class="external">parameter properties</a>, I'd like to think that they might have actually <em>made use</em> of the new <code>#b</code> syntax and gone with a terser syntax like <code>constructor(public a, #b)</code> instead of ``constructor(public a, private b)`.</li>
</ul>
<a name="Upsides-of-this-proposal"></a>
<h2 >Upsides of this proposal<a href="#Upsides-of-this-proposal" class="wiki-anchor">¶</a></h2>
<ol>
<li>Removes even more boilerplate (all those <code>attr_accessor</code> lines), much of the time</li>
</ol>
<a name="Downsides-of-this-proposal"></a>
<h2 >Downsides of this proposal<a href="#Downsides-of-this-proposal" class="wiki-anchor">¶</a></h2>
<ol>
<li>Only provides a way to define both getter and setter at once. Doesn't provide a way to <em>just</em> define a getter and not a setter, for example.
<ul>
<li>Doesn't seem like a big deal, however. You can just not use this feature and define the getter with <code>attr_reader :a</code> instead. Or define private getter/setter with <code>private @a</code> and then override with <code>attr_reader :a</code> to add a public getter (while keeping the private setter).</li>
</ul>
</li>
</ol> Ruby master - Feature #17834 (Open): Add a Bytes and BytesArray class that implement memoryviewhttps://bugs.ruby-lang.org/issues/178342021-04-26T23:09:54Zdsisnero (Dominic Sisneros)dsisnero@gmail.com
<p>"this is a string".bytes should == Bytes.new('this is a string') # an immutable bytes object that implements memory view</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">bytestring</span> <span class="o">=</span> <span class="no">Bytes</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'this is a string'</span><span class="p">)</span>
<span class="n">mv</span> <span class="o">=</span> <span class="no">Fiddle</span><span class="o">::</span><span class="no">MemoryView</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">bytestring</span><span class="p">)</span>
<span class="n">mv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># 116</span>
</code></pre>
<p>similary String.new('this is a string').bytes == ByteArray.new('this is a string') # a mutable byte array object that implements memoryview , takes an optional encoding that uses current string encoding</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ba</span> <span class="o">=</span> <span class="no">ByteArray</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'this is a string'</span><span class="p">)</span>
<span class="n">mv</span> <span class="o">=</span> <span class="no">Fiddle</span><span class="o">::</span><span class="no">MemoryView</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">ba</span><span class="p">)</span>
<span class="n">mv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="c1"># 116</span>
<span class="n">mv</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="mi">120</span> <span class="c1"># memoryview works on underlying object - changes mv.obj</span>
<span class="n">ba</span><span class="p">.</span><span class="nf">pack</span><span class="p">(</span><span class="s1">'C*'</span><span class="p">).</span><span class="nf">force_encoding</span><span class="p">(</span><span class="s1">'UTF-8'</span><span class="p">)</span> <span class="c1"># 'xhis is a string'</span>
</code></pre>
<p>also it would be good if String#bytes returns the new classes - (return something that implements memoryview) not just plain array<br>
or add a new %b literal that returns an immutable ByteString %b('this is a string')</p> Ruby master - Feature #17833 (Open): add IO.readinto(b) where b is a bytes like object that is yo...https://bugs.ruby-lang.org/issues/178332021-04-26T22:40:00Zdsisnero (Dominic Sisneros)dsisnero@gmail.com
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">f</span> <span class="o">=</span> <span class="no">File</span><span class="p">.</span><span class="nf">open</span><span class="p">(</span><span class="no">FILENAME</span><span class="p">,</span><span class="s1">'rb'</span><span class="p">)</span>
<span class="n">bytearray</span> <span class="o">=</span> <span class="no">ByteArray</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">File</span><span class="p">.</span><span class="nf">size</span><span class="p">(</span><span class="no">FILENAME</span><span class="p">))</span> <span class="c1"># ByteArray implements memoryview</span>
<span class="n">f</span><span class="p">.</span><span class="nf">readinto</span><span class="p">(</span><span class="n">bytearray</span><span class="p">)</span>
</code></pre>
<p>First, a ByteaArray is created and pre-allocated to the size of the data we're going to read into it. The pre-allocation is important - since readinto directly accesses the internal buffer of bytearray, it won't write more than has been allocated. Next, the file.readinto method is used to read the data directly into the bytearray's internal storage, without going via temporary buffers.</p>
<a name="Related"></a>
<h1 >Related<a href="#Related" class="wiki-anchor">¶</a></h1>
<p><a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: Add a Bytes and BytesArray class that implement memoryview (Open)" href="https://bugs.ruby-lang.org/issues/17834">#17834</a><br>
<a class="issue tracker-2 status-8 priority-4 priority-default closed" title="Feature: add slice method to Fiddle::MemoryView (Third Party's Issue)" href="https://bugs.ruby-lang.org/issues/17831">#17831</a></p> Ruby master - Feature #17830 (Assigned): 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 #17496 (Open): Add constant Math::TAUhttps://bugs.ruby-lang.org/issues/174962020-12-31T19:27:40Zjzakiya (Jabari Zakiya)
<p>Excuse me if this has been brought up before.</p>
<p>This is a simple proposal to add the math constant <code>Math::TAU</code> = 2*<code>Math::PI</code>.</p>
<p>See: <a href="https://tauday.com/" class="external">https://tauday.com/</a></p>
<p><code>TAU</code> has been included in a growing number of languages (Rust, Python3, Julia, et al), and this would add Ruby to that list, and make it even cooler. :-)</p> Ruby master - Feature #17326 (Open): Add Kernel#must! to the standard libraryhttps://bugs.ruby-lang.org/issues/173262020-11-14T23:15:30Zjez (Jake Zimmerman)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>We should add a method <code>Kernel#must!</code> (name TBD) which raises if <code>self</code> is <code>nil</code> and returns <code>self</code> otherwise.</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>Ruby 3 introduces type annotations for the standard library.<br>
Type checkers consume these annotations, and report errors for type mismatches.<br>
One of the most common and most valuable type errors is whether <code>nil</code> is allowed as an argument or return value.<br>
Sorbet's type system tracks this, and RBS files have syntax for annotating whether <code>nil</code> is allowed or not.</p>
<p>Since Sorbet checks proper usage of <code>nil</code>, it requires code that looks like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">if</span> <span class="n">thing</span><span class="p">.</span><span class="nf">nil?</span>
<span class="k">raise</span> <span class="s2">"The thing was nil"</span>
<span class="k">end</span>
<span class="n">thing</span><span class="p">.</span><span class="nf">do_something</span>
</code></pre>
<p>This is good because it forces the programmer to acknowledge that the thing might be <code>nil</code>, and declare<br>
that they'd rather raise an exception in that case than handle the <code>nil</code> (of course, there are many other<br>
times where <code>nil</code> is both possible and valid, which is why Sorbet forces at least considering in all cases).</p>
<p>It is annoying and repetitive to have to write these <code>if .nil?</code> checks everywhere to ignore the type error,<br>
so Sorbet provides it as a library function, called <code>T.must</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">T</span><span class="p">.</span><span class="nf">must</span><span class="p">(</span><span class="n">thing</span><span class="p">).</span><span class="nf">do_something</span>
</code></pre>
<p>Sorbet knows that the call to <code>T.must</code> raises if <code>thing</code> is <code>nil</code>.<br>
To make this very concrete, here's a Sorbet playground where you can see this in action:</p>
<p><a href="https://sorbet.run/#%23%20typed%3A%20true%0Aextend%20T%3A%3ASig%0A%0Aclass%20Thing%0A%20%20def%20do_something%3B%20end%0Aend%0A%0Asig%20%7Bparams(thing%3A%20T.nilable(Thing)).void%7D%0Adef%20example1(thing)%0A%20%20%23%20error%2C%20might%20be%20nil%3A%0A%20%20thing.do_something%0Aend%0A%0Asig%20%7Bparams(thing%3A%20T.nilable(Thing)).void%7D%0Adef%20example2(thing)%0A%20%20if%20thing.nil%3F%0A%20%20%20%20raise%20%22The%20thing%20was%20nil%22%0A%20%20end%0A%0A%20%20%23%20no%20error%2C%20because%20it's%20after%20the%20%60if%20.nil%3F%60%20check%3A%0A%20%20thing.do_something%0Aend%0A%0Asig%20%7Bparams(thing%3A%20T.nilable(Thing)).void%7D%0Adef%20example3(thing)%0A%20%20%23%20no%20error%2C%20because%20it's%20after%20the%20%60if%20.nil%3F%60%20check%3A%0A%20%20T.must(thing).do_something%0Aend" class="external">→ View on sorbet.run</a></p>
<p>You can read more about <code>T.must</code> in the <a href="https://sorbet.org/docs/type-assertions#tmust" class="external">Sorbet documentation</a>.</p>
<a name="Problem"></a>
<h1 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h1>
<p>While <code>T.must</code> works, it is not ideal for a couple reasons:</p>
<ol>
<li>
<p>It leads to a weird outward spiral of flow control, which disrupts method chains:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># ┌─────────────────┐</span>
<span class="c1"># │ ┌────┐ │</span>
<span class="c1"># ▼ ▼ │ │</span>
<span class="no">T</span><span class="p">.</span><span class="nf">must</span><span class="p">(</span><span class="no">T</span><span class="p">.</span><span class="nf">must</span><span class="p">(</span><span class="n">task</span><span class="p">).</span><span class="nf">mailing_params</span><span class="p">).</span><span class="nf">fetch</span><span class="p">(</span><span class="s1">'template_context'</span><span class="p">)</span>
<span class="c1"># │ │ ▲ ▲</span>
<span class="c1"># │ └──────────┘ │</span>
<span class="c1"># └─────────────────────────────────┘</span>
</code></pre>
<p>compare that control flow with this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># ┌────┐┌────┐┌─────────────┐┌────┐</span>
<span class="c1"># │ ▼│ ▼│ ▼│ ▼</span>
<span class="n">task</span><span class="p">.</span><span class="nf">must!</span><span class="p">.</span><span class="nf">mailing_params</span><span class="p">.</span><span class="nf">must!</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="s1">'template_context'</span><span class="p">)</span>
</code></pre>
</li>
<li>
<p>It is not a method, so you can't <code>map</code> it over a list using <code>Symbol#to_proc</code>. Instead, you have to expand the block:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array_of_integers</span> <span class="o">=</span> <span class="n">array_of_nilable_integers</span><span class="p">.</span><span class="nf">map</span> <span class="p">{</span><span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="no">T</span><span class="p">.</span><span class="nf">must</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="p">}</span>
</code></pre>
<p>Compare that with this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array_of_integers</span> <span class="o">=</span> <span class="n">array_of_nilable_integers</span><span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="ss">:must!</span><span class="p">)</span>
</code></pre>
</li>
<li>
<p>It is in a Sorbet-specific gem. We do not intend for Sorbet to be the only type checker.<br>
It would be nice to have such a method in the Ruby standard library so that it can be shared by all type checkers.</p>
</li>
<li>
<p>This method can make Ruby codebases that <strong>don't</strong> use type checkers more robust!<br>
<code>Kernel#must!</code> could be an easy way to assert invariants early.<br>
Failing early makes it more likely that a test will fail, rather than getting <code>TypeError</code>'s and <code>NoMethodError</code>'s in production.<br>
This makes all Ruby code better, not just the Ruby code using types.</p>
</li>
</ol>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>We should extend the Ruby standard library with something like this::</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Kernel</span>
<span class="k">def</span> <span class="nf">must!</span><span class="p">;</span> <span class="nb">self</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">NilClass</span>
<span class="k">def</span> <span class="nf">must!</span>
<span class="k">raise</span> <span class="no">TypeError</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"nil.must!"</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>These methods would get type annotations that look like this:<br>
(using Sorbet's RBI syntax, because I don't know RBS well yet)</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Kernel</span>
<span class="n">sig</span> <span class="p">{</span><span class="n">returns</span><span class="p">(</span><span class="no">T</span><span class="p">.</span><span class="nf">self_type</span><span class="p">)}</span>
<span class="k">def</span> <span class="nf">must!</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">NilClass</span>
<span class="n">sig</span> <span class="p">{</span><span class="n">returns</span><span class="p">(</span><span class="no">T</span><span class="p">.</span><span class="nf">noreturn</span><span class="p">)}</span>
<span class="k">def</span> <span class="nf">must!</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>What these annotations say:</p>
<ul>
<li>
<p>In <code>Kernel#must!</code>, the return value is <code>T.self_type</code>, or "whatever the type of the receiver was."<br>
That means that <code>0.must!</code> will have type <code>Integer</code>, <code>"".must!</code> will have type <code>String</code>, etc.</p>
</li>
<li>
<p>In <code>NilClass#must!</code>, there is an override of <code>Kernel#must!</code> with return type <code>T.noreturn</code>.<br>
This is a fancy type that says "this code either infinitely loops or raises an exception."<br>
This is the name for Sorbet's <a href="https://en.wikipedia.org/wiki/Bottom_type" class="external">bottom type</a>, if you<br>
are familiar with that terminology.</p>
</li>
</ul>
<p>Here is a Sorbet example where you can see how these annotations behave:</p>
<p><a href="https://sorbet.run/#%23%20typed%3A%20true%0A%0Amodule%20Kernel%0A%20%20T%3A%3ASig%3A%3AWithoutRuntime.sig%20%7Breturns(T.self_type)%7D%0A%20%20def%20must!%3B%20self%3B%20end%0Aend%0A%0Aclass%20NilClass%0A%20%20T%3A%3ASig%3A%3AWithoutRuntime.sig%20%7Breturns(T.noreturn)%7D%0A%20%20def%20must!%0A%20%20%20%20raise%20TypeError.new(%22nil.must!%22)%0A%20%20end%0Aend%0A%0Axs%20%3D%20T%3A%3AArray%5BInteger%5D.new(%5B0%5D)%0AT.reveal_type(xs.first)%20%20%20%20%20%20%20%23%20T.nilable(Integer)%0AT.reveal_type(xs.first.must!)%20%23%20Integer%0A%0Ays%20%3D%20T%3A%3AArray%5BT.nilable(Integer)%5D.new(%5B0%2C%20nil%2C%201%2C%20nil%2C%202%5D)%0AT.reveal_type(ys)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20T%3A%3AArray%5BT.nilable(Integer)%5D%0AT.reveal_type(ys.map(%26%3Amust!))%20%23%20T%3A%3AArray%5BInteger%5D" class="external">→ View on sorbet.run</a></p>
<a name="Alternatives-considered"></a>
<h1 >Alternatives considered<a href="#Alternatives-considered" class="wiki-anchor">¶</a></h1>
<p>There was some discussion of this feature at the Feb 2020 Ruby Types discussion:</p>
<p>Summarizing:</p>
<ul>
<li>
<p>Sorbet team frequently recommends people to use <code>xs.fetch(0)</code> instead of <code>T.must(xs[0])</code><br>
on <code>Array</code>'s and <code>Hash</code>'s because it chains and reads better.<br>
<code>.fetch</code> not available on other classes.</p>
</li>
<li>
<p>It's intentional that <code>T.must</code> requires as many characters as it does.<br>
Making it slightly annoying to type encourages developers to refactor their code so that <code>nil</code> never occurs.</p>
</li>
<li>
<p>There was a proposal to introduce new syntax like <code>thing.!!</code>. This is currently a syntax error.</p>
<p><strong>Rebuttal</strong>: There is burden to introducing new syntax. Tools like Rubocop, Sorbet, and syntax highlighting<br>
plugins have to be updated. Also: it is hard to search for on Google (as a new Ruby developer). Also: it<br>
is very short—having something slightly shorter makes people think about whether they want to type it out<br>
instead of changing the code so that <code>nil</code> can't occur.</p>
</li>
</ul>
<p>Another alternative would be to dismiss this as "not useful / common enough". I don't think that's true.<br>
Here are some statistics from Stripe's Ruby monolith (~10 million lines of code):</p>
<table>
<thead>
<tr>
<th>methood</th>
<th>percentage of files mentioning method</th>
<th>number of occurrences of method</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>.nil?</code></td>
<td>16.69%</td>
<td>31340</td>
</tr>
<tr>
<td><code>T.must</code></td>
<td>23.89%</td>
<td>74742</td>
</tr>
</tbody>
</table>
<p>From this, we see that</p>
<ul>
<li>
<code>T.must</code> is in 1.43x more files than <code>.nil?</code>
</li>
<li>
<code>T.must</code> occurs 2.38x more often than <code>.nil?</code>
</li>
</ul>
<a name="Naming"></a>
<h1 >Naming<a href="#Naming" class="wiki-anchor">¶</a></h1>
<p>I prefer <code>must!</code> because it is what the method in Sorbet is already called.</p>
<p>I am open to naming suggestions. Please provide reasoning.</p>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<p>In the above example, I used <code>T.must</code> twice. An alternative way to have written that would have been using save navigation:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">T</span><span class="p">.</span><span class="nf">must</span><span class="p">(</span><span class="n">task</span><span class="o">&</span><span class="p">.</span><span class="nf">mailing_params</span><span class="p">).</span><span class="nf">fetch</span><span class="p">(</span><span class="s1">'template_context'</span><span class="p">)</span>
</code></pre>
<p>This works as well. The proposed <code>.must!</code> method works just as well when chaining methods with safe navigation:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">task</span><span class="o">&</span><span class="p">.</span><span class="nf">mailing_params</span><span class="p">.</span><span class="nf">must!</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="s1">'template_context'</span><span class="p">)</span>
</code></pre>
<p>However, there is still merit in using <code>T.must</code> (or <code>.must!</code>) twice—it calls out that the programmer<br>
intended neither location to be <code>nil</code>. In fact, if this method had been chained across multiple lines,<br>
the backtrace would include line numbers saying specifically <strong>which</strong> <code>.must!</code> failed:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">task</span><span class="p">.</span><span class="nf">must!</span>
<span class="p">.</span><span class="nf">mailing_params</span><span class="p">.</span><span class="nf">must!</span>
<span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="s1">'template_context'</span><span class="p">)</span>
</code></pre> Ruby master - Feature #17165 (Open): Add `filter` and `flatten` keywords to `Enumerable#map`https://bugs.ruby-lang.org/issues/171652020-09-12T14:46:54Zsawa (Tsuyoshi Sawada)
<p>I had a use case to do <code>map</code> on an enumerable, with 1-level flattening, while skipping <code>nil</code> values.</p>
<p>There are convenient <code>Enumerable#flat_map</code> and <code>Enumerable#filter_map</code> methods, but the problem is that they cannot be used at the same time. I had to chose to do either of the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array</span>
<span class="p">.</span><span class="nf">filter_map</span> <span class="k">do</span> <span class="o">|</span><span class="n">foo</span><span class="o">|</span>
<span class="n">bar</span> <span class="o">=</span> <span class="n">baz</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span>
<span class="k">next</span> <span class="k">unless</span> <span class="n">bar</span>
<span class="n">bar</span><span class="p">.</span><span class="nf">map</span><span class="p">{</span><span class="o">...</span><span class="p">}</span>
<span class="k">end</span>
<span class="p">.</span><span class="nf">flatten</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array</span>
<span class="p">.</span><span class="nf">flat_map</span> <span class="k">do</span> <span class="o">|</span><span class="n">foo</span><span class="o">|</span>
<span class="n">bar</span> <span class="o">=</span> <span class="n">baz</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span>
<span class="k">next</span> <span class="k">unless</span> <span class="n">bar</span>
<span class="n">bar</span><span class="p">.</span><span class="nf">map</span><span class="p">{</span><span class="o">...</span><span class="p">}</span>
<span class="k">end</span>
<span class="p">.</span><span class="nf">compact</span>
</code></pre>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array</span>
<span class="p">.</span><span class="nf">flat_map</span> <span class="k">do</span> <span class="o">|</span><span class="n">foo</span><span class="o">|</span>
<span class="n">bar</span> <span class="o">=</span> <span class="n">baz</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span>
<span class="k">next</span> <span class="p">[]</span> <span class="k">unless</span> <span class="n">bar</span>
<span class="n">bar</span><span class="p">.</span><span class="nf">map</span><span class="p">{</span><span class="o">...</span><span class="p">}</span>
<span class="k">end</span>
</code></pre>
<p>The last one of the above may not look so bad, but it requires an extra consideration, and is a bit hacky. When you are in a hurry, it just might not come to your mind.</p>
<p>This led me to realize that <code>flat_map</code> and <code>filter_map</code> should not be independent operations, but are rather some different modes of the operation <code>map</code>. There is no reason for the modes to be mutually exclusive of one another, and a use case that I mentioned above may arise.</p>
<p>I propose to add <code>filter</code> and <code>flatten</code> as optional keyword arguments to <code>Enumerable#map</code>.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array</span>
<span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="ss">filter: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">flatten: </span><span class="mi">1</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">foo</span><span class="o">|</span>
<span class="n">bar</span> <span class="o">=</span> <span class="n">baz</span><span class="p">(</span><span class="n">foo</span><span class="p">)</span>
<span class="k">next</span> <span class="k">unless</span> <span class="n">bar</span>
<span class="n">bar</span><span class="p">.</span><span class="nf">map</span><span class="p">{</span><span class="o">...</span><span class="p">}</span>
<span class="k">end</span>
</code></pre>
<p>In fact, even when the two parameters are not used together, I believe it would be easier to the brain and I would feel much more comfortable to pass <code>filter: true</code> or <code>flatten: 1</code> to <code>map</code> when necessary rather than having to deicide whether to use <code>map</code> or <code>flat_map</code> or use <code>map</code> or <code>filter_map</code>.</p>
<p>Furthermore, this would make it possible to do flattening of an arbitrary depth (as specified by the parameter) during map.</p> Ruby master - Feature #17155 (Open): Add a Diggable mixinhttps://bugs.ruby-lang.org/issues/171552020-09-05T14:05:09Zjanfri (Jan Friedrich)janfri26@gmail.com
<p>Ruby 2.3 introduced the <code>#dig</code> method as a general way to access elements in deep structures. Initially it was implemented only for <code>Array</code> and <code>Hash</code>. In the meanwhile also the classes <code>Struct</code>, <code>OpenStruct</code> and <code>Set</code> have a <code>#dig</code> method. There is also a <a href="https://bugs.ruby-lang.org/issues/16425" class="external">proposal</a> to implement <code>#dig</code> for <code>Thread</code>.</p>
<p>In my development I have own classes which have a <code>#[]</code> method implemented and are also candidates for a <code>#dig</code> method. But implementing <code>#dig</code> isn't so trivial as it seems: you have to handle some corner cases. This is the intention for my proposal: Add a <code>Diggable</code> mixin to Ruby (core or stdlib). A simple implementation of it could be something like this:</p>
<pre><code class="Ruby syntaxhl" data-language="Ruby"><span class="k">module</span> <span class="nn">Diggable</span>
<span class="k">def</span> <span class="nf">dig</span> <span class="o">*</span><span class="n">args</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">args</span><span class="p">.</span><span class="nf">shift</span>
<span class="n">o</span> <span class="o">=</span> <span class="nb">self</span><span class="p">[</span><span class="n">a</span><span class="p">]</span>
<span class="k">return</span> <span class="n">o</span> <span class="k">if</span> <span class="n">args</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">o</span><span class="p">.</span><span class="nf">nil?</span>
<span class="n">o</span><span class="p">.</span><span class="nf">send</span> <span class="ss">:dig</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>So you could simply include <code>Diggable</code> to any class which implements <code>#[],</code> and you would get a <code>#dig</code> method for free. Like <code>Comparable</code> or <code>Enumerable</code> for which you have to implement <code>#<=></code> respectively <code>#each</code> and get other methods implemented in this mixins.</p> Ruby master - Feature #16946 (Open): Add an `intersperse` methodhttps://bugs.ruby-lang.org/issues/169462020-06-10T10:00:08Zsos4nt (Stefan Schüßler)mail@stefanschuessler.de
<p>Haskell has an <code>intersperse</code> function which adds a separator between elements of a list.</p>
<p>It would be pretty useful to have such method(s) in Ruby, too.</p>
<p>Examples for <code>Array</code> and <code>String</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span><span class="nf">intersperse</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="c1">#=> [1, 0, 2, 0, 3]</span>
<span class="s1">'Hello'</span><span class="p">.</span><span class="nf">intersperse</span><span class="p">(</span><span class="s1">'-'</span><span class="p">)</span>
<span class="c1">#=> "H-e-l-l-o"</span>
</code></pre>
<p>I'm aware that I can achieve the above with built-in methods, but it's quite cumbersome: (requiring regular expressions / intermediate arrays)</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span><span class="nf">flat_map</span> <span class="p">{</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span> <span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="mi">0</span><span class="p">]</span> <span class="p">}[</span><span class="mi">0</span><span class="o">...-</span><span class="mi">1</span><span class="p">]</span>
<span class="c1">#=> [1, 0, 2, 0, 3]</span>
<span class="s1">'Hello'</span><span class="p">.</span><span class="nf">gsub</span><span class="p">(</span><span class="sr">/(?<=.)./</span><span class="p">,</span> <span class="s1">'-\0'</span><span class="p">)</span>
<span class="c1">#=> "H-e-l-l-o"</span>
<span class="s1">'Hello'</span><span class="p">.</span><span class="nf">chars</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s1">'-'</span><span class="p">)</span>
<span class="c1">#=> "H-e-l-l-o"</span>
</code></pre> Ruby master - Feature #16937 (Assigned): Add DNS over HTTP to Resolvhttps://bugs.ruby-lang.org/issues/169372020-06-07T23:46:44Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>This adds a DNS over HTTP resolver at Resolv::DoH</p>
<p>It obeys RFC8484 with respect to Cache-Control and Age behavior, but does not use HTTP2 as ruby does not have an HTTP2 client.</p>
<p>It does not allow configuration of the Net::HTTP instance beyond timeouts, but I am willing to add more configuration if this is desired.</p> Ruby master - Feature #16929 (Open): Add GC.start(compact: true)https://bugs.ruby-lang.org/issues/169292020-06-01T15:42:53Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>I have been working on integrating compaction in to the normal GC process (in other words, making compaction automatic). I was thinking about adding <code>GC.start(compact: true)</code> (actually I put it in master without filing a ticket first, and I apologize for doing that).</p>
<p>Right now we use <code>GC.compact</code>, but if compaction becomes part of the normal GC process, it probably makes more sense for the API to be <code>GC.start(compact: true)</code> since that is the API most people use for kicking off a GC.</p>
<p>I am going to change the implementation of <code>GC.compact</code> like this:</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/gc.rb b/gc.rb
index 881b8659ce..583122db45 100644
</span><span class="gd">--- a/gc.rb
</span><span class="gi">+++ b/gc.rb
</span><span class="p">@@ -165,7 +165,8 @@</span> def self.latest_gc_info hash_or_key = nil
end
def self.compact
<span class="gd">- __builtin_rb_gc_compact
</span><span class="gi">+ # last option runs compact.
+ __builtin_gc_start_internal true, true, true, true
</span> end
# call-seq:
</code></pre>
<p>But this could be executed from <code>GC.start</code> too.</p>
<p>Should we add <code>GC.start(compact: true)</code> and deprecate <code>GC.compact</code>? I would still like to keep <code>GC.verify_compaction_references</code> for debugging compaction problems (but maybe change the method name), but I don't know if we need to keep <code>GC.compact</code>.</p>
<p>Thanks.</p> Ruby master - Feature #16913 (Open): Add `ARGF#each_io`https://bugs.ruby-lang.org/issues/169132020-05-25T23:33:48Zprajjwal (Prajjwal Singh)
<p>Add an iterator for each file supplied on the command line, or STDIN. <code>ARGF#each_io</code></p>
<a name="Current-Status"></a>
<h2 >Current Status<a href="#Current-Status" class="wiki-anchor">¶</a></h2>
<p>Often, we need to do something with individual files ARGF knows about rather than the concatenation of them. We can combine <code>ARGF#to_io</code> and <code>ARGF#skip</code> to achieve this as follows:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">while</span> <span class="p">(</span><span class="n">file</span> <span class="o">=</span> <span class="no">ARGF</span><span class="p">.</span><span class="nf">to_io</span><span class="p">)</span>
<span class="k">break</span> <span class="k">if</span> <span class="n">file</span><span class="p">.</span><span class="nf">closed?</span> <span class="o">||</span> <span class="n">file</span><span class="p">.</span><span class="nf">eof?</span>
<span class="n">csv</span> <span class="o">=</span> <span class="no">CSV</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
<span class="n">csv</span><span class="p">.</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span> <span class="nb">p</span> <span class="n">line</span> <span class="p">}</span>
<span class="no">ARGF</span><span class="p">.</span><span class="nf">skip</span>
<span class="k">end</span>
</code></pre>
<a name="Proposal"></a>
<h2 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h2>
<p>Add an iterator <code>ARGF#each_io</code> to do the above. The above example would then become:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">ARGF</span><span class="p">.</span><span class="nf">each_io</span> <span class="k">do</span> <span class="o">|</span><span class="n">io</span><span class="o">|</span>
<span class="n">csv</span> <span class="o">=</span> <span class="no">CSV</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">io</span><span class="p">)</span>
<span class="n">csv</span><span class="p">.</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span> <span class="nb">p</span> <span class="n">line</span> <span class="p">}</span>
<span class="k">end</span>
</code></pre>
<p>The name is <code>#each_io</code>. We could call it <code>#each_file</code> as well, but <code>ARGF#to_io</code> emits an <code>IO</code> object when the current file is <code>STDIN</code>.</p>
<a name="Implementation"></a>
<h2 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h2>
<p>A cursory ruby implementation is below. Could better handle the <code>STDIN</code> edge case, and would probably be better off being written in C.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nc">ARGF</span><span class="o">.</span><span class="nf">each_io</span><span class="p">(</span><span class="o">&</span><span class="n">fn</span><span class="p">)</span>
<span class="k">raise</span> <span class="s1">'ARGF#each_io needs a block!'</span> <span class="k">unless</span> <span class="nb">block_given?</span>
<span class="k">while</span> <span class="p">(</span><span class="n">file</span> <span class="o">=</span> <span class="n">to_io</span><span class="p">)</span>
<span class="k">break</span> <span class="k">if</span> <span class="n">file</span><span class="p">.</span><span class="nf">closed?</span> <span class="o">||</span> <span class="n">file</span><span class="p">.</span><span class="nf">eof?</span>
<span class="n">fn</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
<span class="c1"># File was STDIN, no need to go any further.</span>
<span class="k">break</span> <span class="k">if</span> <span class="n">file</span><span class="p">.</span><span class="nf">class</span> <span class="o">==</span> <span class="no">IO</span>
<span class="n">skip</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<a name="Issues"></a>
<h2 >Issues<a href="#Issues" class="wiki-anchor">¶</a></h2>
<ul>
<li>Handling the <code>STDIN</code> edge case is ugly.</li>
<li>Not clear if <code>eof?</code> checking for <code>STDIN</code> should be left up to the user instead.</li>
<li>A real world implementation should return a proper iterator instead of the above.</li>
</ul> Ruby master - Feature #16899 (Open): Add method `Array#both_end`https://bugs.ruby-lang.org/issues/168992020-05-17T16:51:15ZS_H_ (Shun Hiraoka)gamelinks007@gmail.com
<p>Add a method that gets both the first and the last elements of an array: <code>Array#both_end</code>.</p>
<a name="Current-Status"></a>
<h2 >Current Status<a href="#Current-Status" class="wiki-anchor">¶</a></h2>
<p>Sometimes, we want to get the elements at both ends of an array. But now, no method has this behavior.</p>
<p>So, define this method:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Array</span>
<span class="k">def</span> <span class="nf">get_first_and_last</span><span class="p">(</span><span class="n">count</span><span class="p">)</span>
<span class="p">[</span><span class="nb">self</span><span class="p">.</span><span class="nf">first</span><span class="p">(</span><span class="n">count</span><span class="p">),</span> <span class="nb">self</span><span class="p">.</span><span class="nf">last</span><span class="p">(</span><span class="n">count</span><span class="p">)]</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<a name="Proposal"></a>
<h2 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h2>
<p>Get the elements at both ends of an array with <code>Array#both_end</code>.</p>
<p>Implement a new method <code>Array#both_end</code> that gets the elements at both ends of an array.</p>
<a name="Arrayboth_end-behavior"></a>
<h2 >Array#both_end behavior<a href="#Arrayboth_end-behavior" class="wiki-anchor">¶</a></h2>
<p>Normal array:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"w"</span><span class="p">,</span> <span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"z"</span> <span class="p">]</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">both_end</span> <span class="c1">#=> ["w", "z"]</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">both_end</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1">#=> [["w", "x"], ["y", "z"]</span>
</code></pre>
<p>Empty array:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">[].</span><span class="nf">both_end</span> <span class="c1">#=> [nil, nil]</span>
<span class="p">[].</span><span class="nf">both_end</span> <span class="c1">#=> [nil, nil]</span>
</code></pre>
<p>Argument exceeds the array size:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"w"</span><span class="p">,</span> <span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"z"</span> <span class="p">]</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">both_end</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="c1">#=> [[ "w", "x", "y", "z" ], [ "w", "x", "y", "z" ]]</span>
</code></pre>
<a name="Implementation"></a>
<h2 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h2>
<p>This implementation uses <code>Array#asscoc</code>, <code>Array#first</code>, and <code>Array#last</code> in C function.</p>
<pre><code class="c syntaxhl" data-language="c"><span class="k">static</span> <span class="n">VALUE</span>
<span class="nf">rb_ary_both_end</span><span class="p">(</span><span class="kt">int</span> <span class="n">argc</span><span class="p">,</span> <span class="n">VALUE</span> <span class="o">*</span><span class="n">argv</span><span class="p">,</span> <span class="n">VALUE</span> <span class="n">ary</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">VALUE</span> <span class="n">first</span><span class="p">,</span> <span class="n">last</span><span class="p">;</span>
<span class="n">rb_check_arity</span><span class="p">(</span><span class="n">argc</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="k">if</span> <span class="p">(</span><span class="n">RARRAY_LEN</span><span class="p">(</span><span class="n">ary</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">return</span> <span class="n">rb_assoc_new</span><span class="p">(</span><span class="n">Qnil</span><span class="p">,</span> <span class="n">Qnil</span><span class="p">);</span>
<span class="n">first</span> <span class="o">=</span> <span class="n">rb_ary_first</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">,</span> <span class="n">ary</span><span class="p">);</span>
<span class="n">last</span> <span class="o">=</span> <span class="n">rb_ary_last</span><span class="p">(</span><span class="n">argc</span><span class="p">,</span> <span class="n">argv</span><span class="p">,</span> <span class="n">ary</span><span class="p">);</span>
<span class="k">return</span> <span class="n">rb_assoc_new</span><span class="p">(</span><span class="n">first</span><span class="p">,</span> <span class="n">last</span><span class="p">);</span>
<span class="p">}</span>
</code></pre>
<a name="Problem"></a>
<h2 >Problem<a href="#Problem" class="wiki-anchor">¶</a></h2>
<p>I'm wondering if the following code should raise an error, and if so, what kind of error is the best.</p>
<p>Argument exceeds the array size:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span> <span class="o">=</span> <span class="p">[</span> <span class="s2">"w"</span><span class="p">,</span> <span class="s2">"x"</span><span class="p">,</span> <span class="s2">"y"</span><span class="p">,</span> <span class="s2">"z"</span> <span class="p">]</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">both_end</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="c1">#=> error can't get both end value!</span>
</code></pre>
<p>I wonder if this method name (<code>Array#both_end</code>) is the best.</p> Ruby master - Feature #16833 (Assigned): Add Enumerable#empty?https://bugs.ruby-lang.org/issues/168332020-05-06T14:09:02Zf3ndot (Justin Bull)
<p>It was surprising to me that Enumerator, something mixed into Array, does not include <code>#empty?</code>. I think it is reasonable to assume people may have to guard iterating and other logic based on the emptiness of an enumerator, such was my case.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="c1"># pretend there's convoluted enumerator logic to produce this structure</span>
<span class="n">table_rows</span> <span class="o">=</span> <span class="p">[{</span> <span class="ss">data: </span><span class="p">[</span><span class="s1">'First'</span><span class="p">,</span> <span class="s1">'Second'</span><span class="p">,</span> <span class="s1">'Third'</span><span class="p">],</span> <span class="ss">config: </span><span class="p">{}</span> <span class="p">},</span> <span class="p">{</span> <span class="ss">data: </span><span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">],</span> <span class="ss">config: </span><span class="p">{</span> <span class="ss">color: </span><span class="s1">'red'</span> <span class="p">}</span> <span class="p">}].</span><span class="nf">to_enum</span>
<span class="k">return</span> <span class="k">if</span> <span class="n">table_rows</span><span class="p">.</span><span class="nf">empty?</span>
<span class="n">table_header</span> <span class="o">=</span> <span class="n">table_rows</span><span class="p">.</span><span class="nf">first</span><span class="p">[</span><span class="ss">:data</span><span class="p">]</span> <span class="c1"># requires an empty guard</span>
<span class="c1"># ...</span>
</code></pre>
<p>I propose that it simply behaves as <code>#take(1).to_a.empty?</code> instead of aliasing to something like <code>#none?</code> because of falsey elements or <code>#size == 0</code> because of potential <code>nil</code> returns:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">[].</span><span class="nf">to_enum</span><span class="p">.</span><span class="nf">empty?</span> <span class="c1"># => true</span>
<span class="p">[</span><span class="kp">false</span><span class="p">].</span><span class="nf">to_enum</span><span class="p">.</span><span class="nf">empty?</span> <span class="c1"># => false</span>
<span class="p">[</span><span class="kp">nil</span><span class="p">].</span><span class="nf">to_enum</span><span class="p">.</span><span class="nf">empty?</span> <span class="c1"># => false</span>
<span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">to_enum</span><span class="p">.</span><span class="nf">empty?</span> <span class="c1"># => false</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span><span class="nf">to_enum</span><span class="p">.</span><span class="nf">empty?</span> <span class="c1"># => false</span>
</code></pre> Ruby master - Feature #16761 (Open): Add an API to move the entire heap, as to make testing GC.co...https://bugs.ruby-lang.org/issues/167612020-04-06T08:30:01Zbyroot (Jean Boussier)byroot@ruby-lang.org
<p>We recently started testing GC.compact effectiveness in production, and one challenge we faced was to ensure that C extensions were compatible with it.</p>
<p>Here's two examples of C-extensions which caused various issues, and their respective fixes:</p>
<ul>
<li><a href="https://github.com/Shopify/liquid-c/pull/55" class="external">https://github.com/Shopify/liquid-c/pull/55</a></li>
<li><a href="https://github.com/brianmario/mysql2/pull/1115" class="external">https://github.com/brianmario/mysql2/pull/1115</a></li>
</ul>
<p>Every time the fix is quite straightforward, my problem is that it's almost impossible to write a reliable test case for it.</p>
<p>With liquid-c I was able to reproduce the issue fairly constantly by calling <code>GC.compact</code> after loading the extension,<br>
but for some reason I was totally unable to do the same with <code>mysql2</code>. And even in production, the issue would only happen on a small number of processes.</p>
<p>This makes me believe that having a debug method to move <strong>all</strong> objects on the heap would be very useful in this scenarios.<br>
There is already several <code>GC.verify_*</code> method intended to be used in debug scenarios, so there's precedent.</p>
<p>I think something like <code>GC.move_all_the_heap</code> would make such testing much easier. e.g.</p>
<pre><code>require 'c-ext'
GC.move_all_the_heap
# run the library tests
</code></pre>
<p>cc <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/73">@tenderlovemaking (Aaron Patterson)</a></p> Ruby master - Feature #16757 (Open): Add intersection to Rangehttps://bugs.ruby-lang.org/issues/167572020-04-03T21:29:34Zstuyam (Stuart Yamartino)
<p>It would be great if there was a way to do an intersection with ranges. I wrote a method recently to solve this but it gets complicated and doesn't solve for all edge cases.<br>
The example I was using it for was getting the intersection of two date ranges. I was using it to calculate pricing discounts for overlapping dates for a reservation system.</p>
<p>I would propose something like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mo">03</span><span class="p">)</span><span class="o">..</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mi">20</span><span class="p">))</span> <span class="o">&</span> <span class="p">(</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span><span class="o">..</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mi">30</span><span class="p">))</span>
<span class="o">=></span> <span class="no">Wed</span><span class="p">,</span> <span class="mi">15</span> <span class="no">Apr</span> <span class="mi">2020</span><span class="o">..</span><span class="no">Mon</span><span class="p">,</span> <span class="mi">20</span> <span class="no">Apr</span> <span class="mi">2020</span>
</code></pre>
<p>There are a handful of array methods that you can just convert a range to and do on an arrays rather than the ranges themselves, like so:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mo">03</span><span class="p">)</span><span class="o">..</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mi">20</span><span class="p">)).</span><span class="nf">to_a</span> <span class="o">&</span> <span class="p">(</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mi">15</span><span class="p">)</span><span class="o">..</span><span class="no">Date</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="mi">2020</span><span class="p">,</span> <span class="mo">04</span><span class="p">,</span> <span class="mi">30</span><span class="p">)).</span><span class="nf">to_a</span>
<span class="o">=></span> <span class="p">[</span><span class="no">Wed</span><span class="p">,</span> <span class="mi">15</span> <span class="no">Apr</span> <span class="mi">2020</span><span class="p">,</span> <span class="no">Thu</span><span class="p">,</span> <span class="mi">16</span> <span class="no">Apr</span> <span class="mi">2020</span><span class="p">,</span> <span class="no">Fri</span><span class="p">,</span> <span class="mi">17</span> <span class="no">Apr</span> <span class="mi">2020</span><span class="p">,</span> <span class="no">Sat</span><span class="p">,</span> <span class="mi">18</span> <span class="no">Apr</span> <span class="mi">2020</span><span class="p">,</span> <span class="no">Sun</span><span class="p">,</span> <span class="mi">19</span> <span class="no">Apr</span> <span class="mi">2020</span><span class="p">,</span> <span class="no">Mon</span><span class="p">,</span> <span class="mi">20</span> <span class="no">Apr</span> <span class="mi">2020</span><span class="p">]</span>
</code></pre>
<p>There are a few issues with this however:</p>
<ol>
<li>Performance: creating the ranges into arrays and doing array calculations can me slower based on the span of the range.</li>
<li>Returning a range: if you want to go back to a range, you need to convert the resulting array back to a range, which involves min and maxing the array and handling nil edge cases.</li>
<li>Infinite ranges: Now that there are endless and beginless ranges added in ruby 2.6 and 2.7 respectively, you can not convert an infinite range to an array and therefore can't do an intersection without more complex logic.</li>
</ol>
<p>I think the added infinite range support makes it a good reason to add range intersections since that is a feature you can't accomplish with just an array.</p>
<p>It looks like there was an <a href="https://bugs.ruby-lang.org/issues/16155" class="external">Array#intersection alias</a> added for Array#& recently. I would propose Range#& and Range#intersection to have parity with Array and Set methods.</p> Ruby master - Feature #16665 (Open): Add an Array#except_index methodhttps://bugs.ruby-lang.org/issues/166652020-02-29T14:46:05Zalex_golubenko (Alex Golubenko)
<p>The main idea is to implement a method that we can use to exclude elements from the array by their indices.</p>
<p>For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="sx">%w( a b c d e f)</span><span class="p">.</span><span class="nf">except_index</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="o">=></span> <span class="p">[</span><span class="s2">"b"</span><span class="p">,</span> <span class="s2">"c"</span><span class="p">,</span> <span class="s2">"d"</span><span class="p">,</span> <span class="s2">"e"</span><span class="p">]</span>
<span class="sx">%w( a b c d e f g h )</span><span class="p">.</span><span class="nf">except_index</span><span class="p">(</span><span class="mi">0</span><span class="o">..</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="o">-</span><span class="mi">2</span><span class="o">..-</span><span class="mi">1</span><span class="p">)</span>
<span class="o">=></span> <span class="p">[</span><span class="s2">"c"</span><span class="p">,</span> <span class="s2">"e"</span><span class="p">,</span> <span class="s2">"f"</span><span class="p">]</span>
</code></pre>
<p>I was meeting many questions on the StackOverflow about how to do such functionality also found many topics about it.<br>
So I think it might a helpful addition.</p>
<p>I spent a few days finding the proper solution on Ruby that might be acceptable with integers and ranges(both positive and negative) and has good performance:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="k">def</span> <span class="nf">except_index</span><span class="p">(</span><span class="o">*</span><span class="n">indexes</span><span class="p">)</span>
<span class="n">indexes</span><span class="p">.</span><span class="nf">each_with_object</span><span class="p">(</span><span class="nb">dup</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">ind</span><span class="p">,</span> <span class="n">obj</span><span class="o">|</span>
<span class="n">ind</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Range</span><span class="p">)</span> <span class="p">?</span> <span class="n">ind</span><span class="p">.</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span> <span class="n">obj</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="kp">false</span> <span class="p">}</span> <span class="p">:</span> <span class="n">obj</span><span class="p">[</span><span class="n">ind</span><span class="p">]</span> <span class="o">=</span> <span class="kp">false</span>
<span class="k">end</span><span class="p">.</span><span class="nf">select</span><span class="p">(</span><span class="o">&</span><span class="ss">:itself</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<p>As you can see it's have not the best readability so I think it's a good point to add a built-in method on C.</p> Ruby master - Feature #16381 (Open): Accept resolv_timeout in Net::HTTPhttps://bugs.ruby-lang.org/issues/163812019-11-29T13:33:17Zkirs (Kir Shatrov)shatrov@me.com
<p>This is a follow-up to <a href="https://bugs.ruby-lang.org/issues/15553" class="external">https://bugs.ruby-lang.org/issues/15553</a> and a successor of <a href="https://github.com/ruby/ruby/pull/1806" class="external">https://github.com/ruby/ruby/pull/1806</a> (the credit to Carl Hörberg).</p>
<p>Unlike <a href="https://github.com/ruby/ruby/pull/1806" class="external">https://github.com/ruby/ruby/pull/1806</a>, this patch introduces a separate <code>resolv_timeout</code> Net::HTTP would pass to <code>Socket.tcp</code>.<br>
The idea to have it as a separate value (vs reusing open_timeout) was suggested by Alan Wu. It's helpful in case specifies open_timeout: 1, DNS resolv takes 0.9s and opening TCP connection takes 0.9s, and the total wait time is 1.8s even though the allowed timeout was 1s.</p>
<p>This patch not only makes DNS timeout customizable, but also fixes a bug when wrapping <code>TCPSocket.open</code> into whatever seconds <code>Timeout.timeout</code> would still take 10 seconds because of the nature of blocking resolv operation on many systems (here's a gist to reproduce on Linux: <a href="https://gist.github.com/kirs/5f711099b23ddae7a87ebb082ce43f59" class="external">https://gist.github.com/kirs/5f711099b23ddae7a87ebb082ce43f59</a>).</p>
<p>This problem is not hypothetical, it's something we've been seeing in production fairly often: even with open/read timeouts on Net::HTTP as low as a second, the Ruby process would still be blocked for 10s (system's resolv timeout) in case of DNS issues. And on web servers with blocking IO (e.g. Unicorn) this would cause the loss of capacity.</p> Ruby master - Feature #16282 (Open): Add "call data" wrapper IMEMO object so inline cache can be ...https://bugs.ruby-lang.org/issues/162822019-10-28T23:26:16Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Hi,</p>
<p>Currently the compactor will invalidate all inline caches. I would like to update references in inline caches so we don't have to invalidate. Most inline caches are reachable from instruction sequences, but one cache is not:</p>
<p><a href="https://github.com/ruby/ruby/blob/6147fa82a923e7318f493857023006801ed25eb5/internal.h#L2395" class="external">https://github.com/ruby/ruby/blob/6147fa82a923e7318f493857023006801ed25eb5/internal.h#L2395</a></p>
<p>This static variable can't be reached from the GC. I'd like to introduce a new IMEMO object that wraps this cache, then the GC can reach the cache and update the value.</p>
<p>I've attached a patch that implements the new IMEMO object, and also removes the restriction on GCC so that all compilers get the cache hit.</p>
<p>Does this seem OK shyouhei, ko1?</p> Ruby master - Feature #16245 (Open): Add interfaces to count and measure size all IMEMO objectshttps://bugs.ruby-lang.org/issues/162452019-10-07T22:02:47Zsam.saffron (Sam Saffron)sam.saffron@gmail.com
<p>Koichi introduced an experimental gem: <a href="https://github.com/ko1/iseq_collector" class="external">https://github.com/ko1/iseq_collector</a></p>
<p>It allows:</p>
<p>ObjectSpace.each_iseq{|iseq| ...}<br>
ObjectSpace.count_iseq #=> Integer<br>
ObjectSpace.memsize_of_all_iseq (should not generate RubyVM::InstructionSequence wrappers for IMEMOs)</p>
<p>Since the wrapper object RubyVM::InstructionSequence is lazily allocated, ObjectSpace.each_object does not find these IMEMOs unless they have been wrapped. This design is good and conserves memory.</p>
<p><code>count_iseq</code> and <code>memsize_of_all_iseq</code> are very powerful metrics most large Ruby deployments can use to automatically detect method leaks introduced via meta programming. These issues are invisible now short of walking a heap dump.</p>
<p>Can we add the new interface into 2.7?</p> Ruby master - Feature #16244 (Open): Add a Time#before? and Time#after? methodhttps://bugs.ruby-lang.org/issues/162442019-10-07T16:47:39Zstevendaniels (Steven Daniels)
<p>Comparing times using <code>></code> and<code><</code> can be pretty confusing.</p>
<p>I'd like to propose <code>Time#before?</code> and <code>Time#after?</code> methods for aliasing <code>Time#<</code> and <code>Time#></code></p>
<p>These method aliases would make the code more readable. :)</p>
<p>Current syntax:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">if</span> <span class="n">current_time</span> <span class="o"><</span> <span class="n">expiration_at</span>
<span class="c1"># do stuff</span>
<span class="k">end</span>
<span class="k">if</span> <span class="n">birthday</span> <span class="o">></span> <span class="n">thirteen_years_ago</span>
<span class="c1"># you need a parent's permission to sign up</span>
<span class="k">end</span>
</code></pre>
<p>What I'd like to see added:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">if</span> <span class="n">current_time</span><span class="p">.</span><span class="nf">before?</span> <span class="n">expiration_at</span>
<span class="c1"># do stuff</span>
<span class="k">end</span>
<span class="k">if</span> <span class="n">birthday</span><span class="p">.</span><span class="nf">after?</span> <span class="n">thirteen_years_ago</span>
<span class="c1"># you need a parent's permission to sign up</span>
<span class="k">end</span>
</code></pre>
<p>Thanks for your consideration!</p> Ruby master - Feature #16231 (Open): Add #location to Net::HTTPResponsehttps://bugs.ruby-lang.org/issues/162312019-10-03T03:53:26ZRichSeviora (Richard Seviora)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>Add a location convenience method to the <code>Net::HTTPRedirection</code> class.</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>When developers receive 3xx responses, we tend to do one of two things: follow the redirect or pass the redirect location onto the consumer. In both cases, we need to get the <code>Location</code> header value. This is a common enough use case that I had expected there'd be a convenience method, and there isn't one. I ended up googling how to do this and discovered I had to call the following:</p>
<pre><code>response['Location']
</code></pre>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>My proposal is to return the <code>Location</code> header value as-is (<code>String</code> if present, <code>nil</code> if header is not present) in a <code>#location</code> method added to <code>Net::HTTPResponse</code>. This will permit consumers to access the <code>Location</code> header in all of the response classes.</p>
<p><a href="https://tools.ietf.org/html/rfc7231#section-7.1.2" class="external">Per RFC 7231 section 7.1.2</a> the <code>Location</code> header is not limited to <code>3xx</code> responses; it can also be returned in <code>201 Created</code> responses. Augmenting the <code>Net:HTTPResponse</code> class makes more sense than augmenting (only) the <code>Net::HTTPRedirection</code> class.</p>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<pre><code>class Net::HTTPResponse
# ...
# Returns the location value if present, nil otherwise.
def location
self['Location']
end
# ...
end
</code></pre>
<a name="Evaluation"></a>
<h1 >Evaluation<a href="#Evaluation" class="wiki-anchor">¶</a></h1>
<p>This has nil performance impact when unused, it adds negligible costs over directly executing the same (guesstimate, I have not validated this)</p>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<p>Instead of returning a <code>String</code>, we could instead instantiate and return a <code>URI</code> object when the method is called (with the option to memoize). The implementation would need to handle both absolute and relative URIs, and decide whether to return the absolute resolved URI, or just the relative URI.</p>
<p>I'm leaning towards returning the string as-is, and letting the consumer decide whether they need to instantiate a URI or just pass the string along.</p> Ruby master - Feature #16150 (Open): Add a way to request a frozen string from to_shttps://bugs.ruby-lang.org/issues/161502019-09-07T05:10:37Zheadius (Charles Nutter)headius@headius.com
<p>Much of the time when a user calls to_s, they are just looking for a simple string representation to display or to interpolate into another string. In my brief exploration, the result of to_s is rarely mutated directly.</p>
<p>It seems that we could save a lot of objects by providing a way to explicitly request a <em>frozen</em> string.</p>
<p>For purposes of discussion I will call this to_frozen_string, which is a terrible name.</p>
<p>This would reduce string allocations dramatically when applied to many common to_s calls:</p>
<ul>
<li>Symbol#to_frozen_string could always return the same cached String representation. This method is <em>heavily</em> used by almost all Ruby code that intermingles Symbols and Strings.</li>
<li>nil, true, false, and any other singleton values in the system could similarly cache and return the same String object.</li>
<li>The strings coming from core types could also be in the fstring cache and deduplicated as a result.</li>
<li>User-provided to_s implementations could opt-in to caching and returning the same frozen String object when the author knows that the result will always be the same.</li>
</ul>
<p>A few ideas for what to call this:</p>
<ul>
<li>
<code>to_fstring</code> or <code>fstring</code> reflects internal the "fstring" cache but is perhaps not obvious for most users.</li>
<li>
<code>to_s(frozen: true)</code> is clean but there will be many cases when the kwargs hash doesn't get eliminated, making matters worse.</li>
<li>
<code>def to_s(frozen = false)</code> would be mostly free but may not be compatible with existing to_s params (like <code>Integer#to_s(radix)</code>
</li>
</ul>
<p>This idea was inspired by @schneems's talk at RubyConf Thailand, where he showed significant overhead in ActiveRecord from Symbol#to_s allocation.</p> Ruby master - Feature #16018 (Open): Add a way to deprecate methodshttps://bugs.ruby-lang.org/issues/160182019-07-24T15:04:28Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>Since <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: deprecate constants (Closed)" href="https://bugs.ruby-lang.org/issues/11398">#11398</a>, We have <code>Module#deprecate_constant</code> available. But I wonder, why we don't have a way to deprecate methods? There is already <code>Gem::Deprecate</code> <a href="https://github.com/ruby/ruby/blob/master/lib/rubygems/deprecate.rb" class="external">1</a>, so may be this could be extracted and made more generic?</p>
<p>This might be useful on several places in Ruby code:</p>
<pre><code>$ find . -name \*.rb -type f -exec grep -r '[^_]warn.*deprecate' {} \; | wc -l
66
</code></pre> Ruby master - Feature #15590 (Open): Add dups to Array to find duplicateshttps://bugs.ruby-lang.org/issues/155902019-02-06T11:31:23Zxdmx (Eric Bloom)
<p>Many times I find myself debugging data and the need of finding duplicated values inside of an Array.</p>
<p>Based on the amount of data it could be a simple <code>array.detect { |value| array.count(value) > 1 }</code> or a more performant way like</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">dups_for</span><span class="p">(</span><span class="n">array</span><span class="p">)</span>
<span class="n">duplicated_values</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">array</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">value</span><span class="o">|</span>
<span class="n">duplicated_values</span> <span class="o"><<</span> <span class="n">value</span> <span class="k">if</span> <span class="n">tmp</span><span class="p">[</span><span class="n">value</span><span class="p">]</span>
<span class="n">tmp</span><span class="p">[</span><span class="n">value</span><span class="p">]</span> <span class="o">=</span> <span class="kp">true</span>
<span class="k">end</span>
<span class="n">duplicated_values</span>
<span class="k">end</span>
</code></pre>
<p>It would be awesome if there was a way directly from the core language to call <code>dups</code> (or another name, as it could be too similar to the current <code>dup</code>) on an array in order to get all the duplicated values.</p>
<p>I'd love to create a PR for this, but my C level is non-existent 😞</p> Ruby master - Misc #15514 (Open): Add documentation for implicit array decompositionhttps://bugs.ruby-lang.org/issues/155142019-01-07T10:26:51Zsos4nt (Stefan Schüßler)mail@stefanschuessler.de
<p>The documentation for <a href="http://ruby-doc.org/core/doc/syntax/assignment_rdoc.html#label-Array+Decomposition" class="external">Array Decomposition</a> says: <em>"[...] you can decompose an Array during assignment using parenthesis [sic]"</em> and gives an example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">)</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span><span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="c1"># prints {:a=>1, :b=>2}</span>
</code></pre>
<p>But – as we all know – it's also possible <em>without</em> parentheses, i.e.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span> <span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="c1">#=> {:a=>1, :b=>2}</span>
</code></pre>
<p>This also applies to block arguments when yielding multiple values vs. yielding a single array:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">foo</span>
<span class="k">yield</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">bar</span>
<span class="k">yield</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="k">end</span>
<span class="n">foo</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span><span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="p">}</span>
<span class="c1">#=> {:a=>1, :b=>2}</span>
<span class="n">bar</span> <span class="p">{</span> <span class="o">|</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">|</span> <span class="nb">p</span> <span class="ss">a: </span><span class="n">a</span><span class="p">,</span> <span class="ss">b: </span><span class="n">b</span> <span class="p">}</span>
<span class="c1">#=> {:a=>1, :b=>2}</span>
</code></pre>
<p>In both cases, parentheses are optional.</p>
<p>This implicit array decomposition could be quite surprising for newcomers. The documentation should cover it.</p> Ruby master - Feature #15446 (Open): Add a method `String#each_match` to the Ruby corehttps://bugs.ruby-lang.org/issues/154462018-12-21T09:06:46ZCaryInVictoria (Cary Swoveland)cary@swoveland.com
<p><code>String#each_match</code> would have two forms:</p>
<p><em>each_match(pattern) { |match| block } → str</em><br>
<em>each_match(pattern) → an_enumerator</em></p>
<p>The latter would be identical to the form <em>gsub(pattern) → enumerator</em> of <a href="http://ruby-doc.org/core-2.5.1/String.html#method-i-gsub" class="external">String#gsub</a>. The former would simply yield the matches to a block and return the receiver.</p>
<p>I frequently use the form of <code>gsub</code> that returns an enumerator instead of <code>scan</code> when chaining to Enumerable methods. That's because <code>scan</code> returns an unneeded temporary array. This use of <code>gsub</code> can also be useful when the pattern contains capture groups, which can be a complication when using <code>scan</code>, as in the following example</p>
<p>Suppose we are given a string and wish to count the number of occurrences of each word that begins and ends with the same letter (case-insensitive).</p>
<pre><code> str = "Viv and Bob are party animals. Bob and Eve are a couple who met on Christmas Eve. Bob is a regular guy."
r = /\b(?:[a-z]|([a-z])[a-z]*\1)\b/i
</code></pre>
<p>This regular expression reads, "match a word break, followed by one letter or by two or more letters with the last matching the first (case insensitive), all followed by a word break".</p>
<pre><code> enum = str.each_match(r)
#=> #<Enumerator: "Viv and Bob are party...a regular guy.":gsub(/\b(?:[a-z]|([a-z])[a-z]*\1)\b/i)>
</code></pre>
<p>We can convert <code>enum</code> to an array to see the words that will be generated by the enumerator and passed to the block.</p>
<pre><code>enum.to_a
#=> ["Viv", "Bob", "Bob", "Eve", "a", "Eve", "Bob", "a", "regular"]
</code></pre>
<p>Continuing,</p>
<pre><code>enum.each_with_object(Hash.new(0)) { |word, h| h[word] += 1 }
#=> {"Viv"=>1, "Bob"=>3, "Eve"=>2, "a"=>2, "regular"=>1}
</code></pre>
<p>We could alternatively use <code>each_match</code> with a block.</p>
<pre><code> h = Hash.new(0)
str.each_match(r) { |word| h[word] += 1 }
#=> "Viv and Bob are party animals. Bob and Eve are a couple who met on Christmas Eve. Bob is a regular guy."
h #=> {"Viv"=>1, "Bob"=>3, "Eve"=>2, "a"=>2, "regular"=>1}
</code></pre>
<p>This form of <code>each_match</code> has no counterpart with <code>gsub</code>.</p>
<p>Consider now how <code>scan</code> would be used here. Because of the way <code>scan</code> treats capture groups, we cannot write</p>
<pre><code>str.scan(r)
#=> [["V"], ["B"], ["B"], ["E"], [nil], ["E"], ["B"], [nil], ["r"]]
</code></pre>
<p>Instead we must add a second capture group.</p>
<pre><code>arr = str.scan(/\b((?:[a-z]|([a-z])[a-z]*\2))\b/i)
#=> [["Viv", "V"], ["Bob", "B"], ["Bob", "B"], ["Eve", "E"], ["a", nil], ["Eve", "E"], ["Bob", "B"], ["a", nil], ["regular", "r"]]
</code></pre>
<p>Then</p>
<pre><code>arr.each_with_object(Hash.new(0)) { |(word,_),h| h[word] += 1 }
#=> {"Viv"=>1, "Bob"=>3, "Eve"=>2, "a"=>2, "regular"=>1}
</code></pre>
<p>This works but it's a bit of a <a href="https://dictionary.cambridge.org/us/dictionary/english/a-dog-s-breakfast" class="external">dog's breakfast</a> when compared to the use of the proposed method.</p>
<p>The problem with using <code>gsub</code> in this way is that it is confusing to readers who are expecting character substitutions to be performed. I also believe that the name of this method (the "sub" in <code>gsub</code>) has resulted in the form of the method that returns an enumerator to be under-appreciated and under-used.</p>
<p>Some comments below propose that this suggestion be adopted and, in time, the form of <code>gsub</code> that returns an enumerator be deprecated.</p> Ruby master - Feature #15393 (Open): Add compilation flags to freeze Array and Hash literalshttps://bugs.ruby-lang.org/issues/153932018-12-08T00:42:37Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Hi,</p>
<p>I would like to add VM compilation options to freeze array and hash literals. For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">frozen</span> <span class="o">=</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">InstructionSequence</span><span class="p">.</span><span class="nf">compile</span><span class="p">(</span><span class="o"><<-</span><span class="no">eocode</span><span class="p">,</span> <span class="kp">__FILE__</span><span class="p">,</span> <span class="kp">nil</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="ss">frozen_string_literal: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">frozen_hash_and_array_literal: </span><span class="kp">true</span><span class="p">)</span><span class="sh">
{ 'a' => ['b', { 'c' => 'd' }] }
</span><span class="no">eocode</span>
<span class="nb">puts</span> <span class="n">frozen</span><span class="p">.</span><span class="nf">disasm</span>
</code></pre>
<p>Output is:</p>
<pre><code>$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,34)> (catch: FALSE)
0000 putobject {"a"=>["b", {"c"=>"d"}]}
0002 leave
</code></pre>
<p>Anything nested in the hash that can't be "frozen" will cause it to not be frozen.</p>
<p>For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">not_frozen</span> <span class="o">=</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">InstructionSequence</span><span class="p">.</span><span class="nf">compile</span><span class="p">(</span><span class="o"><<-</span><span class="no">eocode</span><span class="p">,</span> <span class="kp">__FILE__</span><span class="p">,</span> <span class="kp">nil</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="ss">frozen_string_literal: </span><span class="kp">true</span><span class="p">,</span> <span class="ss">frozen_hash_and_array_literal: </span><span class="kp">true</span><span class="p">)</span><span class="sh">
{ 'a' => some_method }
</span><span class="no">eocode</span>
<span class="nb">puts</span> <span class="n">not_frozen</span><span class="p">.</span><span class="nf">disasm</span>
</code></pre>
<p>Output:</p>
<pre><code>$ ./ruby thing.rb
== disasm: #<ISeq:<compiled>@thing.rb:0 (0,0)-(0,24)> (catch: FALSE)
0000 putobject "a"
0002 putself
0003 opt_send_without_block <callinfo!mid:some_method, argc:0, FCALL|VCALL|ARGS_SIMPLE>, <callcache>
0006 newhash 2
0008 leave
</code></pre>
<p>Eventually I would like to freeze array and hash literals in source code itself, but I think this is a good first step.</p>
<p>The reason I want this feature is I think we can reduce some object allocations, and once Guilds are implemented, easily create immutable data.</p>
<p>I've attached a patch that implements the above.</p>
<p>(Also I think maybe "frozen_literals" would be a better name, but I don't want to imply that numbers or booleans are frozen too)</p>
<p>Thanks!</p> Ruby master - Feature #15222 (Open): Add a way to distinguish between Struct classes with and wit...https://bugs.ruby-lang.org/issues/152222018-10-11T13:01:48Zpluff (Pavel Shutsin)
<p>With Ruby 2.5.0 Struct subclasses can have different <code>initialize</code> arguments list based on <code>keyword_init</code> option. However, there is no way in Ruby to distinguish Structs with keyword arguments syntax and without.</p>
<p>I propose a class method <code>keyword_init?</code> that will allow developers to understand if given structure has keyword based initializer or not.</p>
<p>Example use case for serialization:</p>
<pre><code>Foo = Struct.new(:foo, keyword_init: true)
Bar = Struct.new(:bar)
def dump_and_load_struct(object)
serialized = object.to_h
object.class.new(object.class.keyword_init? ? serialized : serialized.values)
end
dump_and_load_struct(Foo.new(foo: 1)) # #<struct Foo foo=1>
dump_and_load_struct(Bar.new(2)) # #<struct Bar bar=1>
</code></pre>
<p>An issue that might be related: <a href="https://bugs.ruby-lang.org/issues/14314" class="external">https://bugs.ruby-lang.org/issues/14314</a></p> Ruby master - Misc #15202 (Open): Adding Coverity Scan to CI to see the result casuallyhttps://bugs.ruby-lang.org/issues/152022018-10-04T14:06:33Zjaruga (Jun Aruga)
<p>Recently I reported issues detected by code analysis tool mainly using Coverity Scan.</p>
<p>The 9 issues categorized as "important" was fixed by <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Fixing issues detected by an Analysis tool. (Closed)" href="https://bugs.ruby-lang.org/issues/15116">#15116</a>. (Thank you!)</p>
<blockquote>
<p><a href="https://bugs.ruby-lang.org/issues/15116" class="external">https://bugs.ruby-lang.org/issues/15116</a></p>
<p>However as a "not important" issues, around 1000 issues were detected by the tool for the ruby 2.5.1.<br>
I am considering how to deal with this or report those.<br>
I might open an another ticket for that.</p>
</blockquote>
<p>However there are around 1000 "not important" issues.</p>
<p>Right now I do not share the report file (840KByte) for that, because it makes people tired.<br>
If someone want to see it, I am happy to share it here as an attachment.</p>
<p>Instead of that, It looks good to me that someone could see the result of coverity scan casually anytime to fix those in long term.</p>
<p>What I want to propose is to add coverity scan test on rubyci or Travis CI.</p>
<p>I do not know how coverity scan is used on current Ruby project as a regular workflow.<br>
But I could see it is actually used from the setting [2] and some tickets. [3]</p>
<p>I found how to use Coverity Scan on Travis CI [4], and the used cases [5][6].</p>
<p>How do you think?</p>
<ul>
<li>[1] rubyci: <a href="https://www.rubyci.org/" class="external">https://www.rubyci.org/</a>
</li>
<li>[2] coverity scan ruby project: <a href="https://scan.coverity.com/projects/ruby" class="external">https://scan.coverity.com/projects/ruby</a>
</li>
<li>[3] coverity scan used tickets:
<ul>
<li><a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/61862" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/61862</a></li>
<li><a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/55763" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/55763</a></li>
<li><a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/50734" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/50734</a></li>
</ul>
</li>
<li>[4] How to use Coverity Scan on Travis CI: <a href="https://scan.coverity.com/travis_ci" class="external">https://scan.coverity.com/travis_ci</a>
</li>
<li>[5] The cases for coverity scan on Travis CI:
<ul>
<li><a href="https://github.com/nanoporetech/scrappie/blob/master/.travis.yml" class="external">https://github.com/nanoporetech/scrappie/blob/master/.travis.yml</a></li>
<li><a href="https://github.com/JanusGraph/janusgraph/blob/master/.travis.yml" class="external">https://github.com/JanusGraph/janusgraph/blob/master/.travis.yml</a></li>
</ul>
</li>
</ul> Ruby master - Feature #15166 (Assigned): 2.5 times faster implementation than current gcd implmen...https://bugs.ruby-lang.org/issues/151662018-09-26T18:30:29Zjzakiya (Jabari Zakiya)
<p>This is to be more explicit (and accurate) than <a href="https://bugs.ruby-lang.org/issues/15161" class="external">https://bugs.ruby-lang.org/issues/15161</a></p>
<p>This is my modified gcd benchmarks code, originally presented by Daniel Lemire (see 15161).</p>
<p><a href="https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566" class="external">https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566</a></p>
<p>Ruby's current implementation of Stein's gcd algorithm is only slightly faster than the<br>
code posted on the wikepedia page, and over 2.5 times slower than the fastest implementation<br>
in the benchmarks.</p>
<pre><code>[jzakiya@localhost ~]$ ./gcdbenchmarks
gcd between numbers in [1 and 2000]
gcdwikipedia7fast32 : time = 99
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 139
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 267
gcdwikipedia2 : time = 321
gcd between numbers in [1000000001 and 1000002000]
gcdwikipedia7fast32 : time = 100
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 138
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 269
gcdwikipedia2 : time = 323
</code></pre>
<p>This is Ruby's code per: <a href="https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307" class="external">https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307</a><br>
which is basically the wikepedia implementation.</p>
<pre><code>inline static long
i_gcd(long x, long y)
{
unsigned long u, v, t;
int shift;
if (x < 0)
x = -x;
if (y < 0)
y = -y;
if (x == 0)
return y;
if (y == 0)
return x;
u = (unsigned long)x;
v = (unsigned long)y;
for (shift = 0; ((u | v) & 1) == 0; ++shift) {
u >>= 1;
v >>= 1;
}
while ((u & 1) == 0)
u >>= 1;
do {
while ((v & 1) == 0)
v >>= 1;
if (u > v) {
t = v;
v = u;
u = t;
}
v = v - u;
} while (v != 0);
return (long)(u << shift);
}
</code></pre>
<p>This is the fastest implementation from the benchmarks. (I originally, wrongly, cited<br>
the implementation in the article, which is 4|5th fastest in benchmarks, but<br>
still almost 2x faster than the Ruby implementation.)</p>
<pre><code>// based on wikipedia's article,
// fixed by D. Lemire, K. Willets
unsigned int gcdwikipedia7fast32(unsigned int u, unsigned int v)
{
int shift, uz, vz;
if ( u == 0) return v;
if ( v == 0) return u;
uz = __builtin_ctz(u);
vz = __builtin_ctz(v);
shift = uz > vz ? vz : uz;
u >>= uz;
do {
v >>= vz;
int diff = v;
diff -= u;
if ( diff == 0 ) break;
vz = __builtin_ctz(diff);
if ( v < u ) u = v;
v = abs(diff);
} while( 1 );
return u << shift;
}
</code></pre>
<p>The key to speeding up all the algorithms is using the <code>__builtin_ctz(x)</code> directive<br>
to determine the number of trailing binary '0's.</p> Ruby master - Misc #14768 (Open): Add documentation for || and &&https://bugs.ruby-lang.org/issues/147682018-05-17T08:41:39Zsos4nt (Stefan Schüßler)mail@stefanschuessler.de
<p>The Ruby documentation doesn't seem to cover <code>||</code> and <code>&&</code>.</p>
<p>The only references I could find are:</p>
<p><a href="http://ruby-doc.org/core-2.5.1/doc/keywords_rdoc.html" class="external">http://ruby-doc.org/core-2.5.1/doc/keywords_rdoc.html</a></p>
<blockquote>
<p><strong>and</strong> – Short-circuit Boolean and with lower precedence than <code>&&</code><br>
<strong>or</strong> – Short-circuit Boolean and with lower precedence than <code>||</code></p>
</blockquote>
<p><a href="http://ruby-doc.org/core-2.5.1/doc/syntax/assignment_rdoc.html" class="external">http://ruby-doc.org/core-2.5.1/doc/syntax/assignment_rdoc.html</a></p>
<blockquote>
<p>There are also <code>||=</code> and <code>&&=</code>. The former makes an assignment if ...</p>
</blockquote>
<p>But there's no documentation for the operators themselves.</p> Ruby master - Feature #14758 (Open): Add a first-class support for isolated bounded packages / mo...https://bugs.ruby-lang.org/issues/147582018-05-15T07:56:25Zgrzesiek (Grzegorz Bizon)grzesiek.bizon@gmail.com
<p>While one of the core principles of Ruby is to extend the language in a way it is a most useful and convenient tool that a software developer can have in their toolbox, lack of a first-class isolation on module level can cause some serious problems when project grows beyond some size.</p>
<p>This is especially visible in large projects, where most of the code lives in the <code>lib/</code> directory, and there are tens or hundreds of modules there. Ideally we would like to make these modules isolated and hide complexity behind facades. Currently it is not possible to isolate such modules, because a developer can still reach beyond boundary of a bounded context, and use <code>MyModule::InternalClass</code> directly.</p>
<p>It is very difficult to enforce boundaries, currently it requires a lot of work to implement complex static analysis rules.</p>
<p>Would it make sense to add support for first-class <code>package</code>, <code>context</code> or <code>boundary</code>, that would be a regular module but would not allow referencing inner constants from outside?</p>
<pre><code>context MyModule
class MyIsolatedClass
# ...
end
def self.build
MyIsolatedClass.new
end
end
MyModule::MyIsolatedClass # raises context violation
MyModule.build # => Returns an instance of MyModule::MyIsolatedClass
</code></pre>
<p>I'm pretty sure that I failed at finding similar feature proposal that has been already submitted, in that case sorry for that!</p>
<p>Please let me know what do you think about that! Thanks in advance! <3</p> Ruby master - Feature #14618 (Open): Add display width method to String for CLIhttps://bugs.ruby-lang.org/issues/146182018-03-19T19:00:23Zaycabta (aycabta .)aycabta@gmail.com
<a name="Abstract"></a>
<h2 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h2>
<p>Unicode has display width data of characters, "Narrow" or "Wide".<br>
For example, "A" is "Narrow", "💎" ("\u{1f48e}") is "Wide".<br>
<a href="http://unicode.org/reports/tr11/" class="external">http://unicode.org/reports/tr11/</a><br>
This data is very important for CLI tools.</p>
<a name="Use-case"></a>
<h2 >Use-case<a href="#Use-case" class="wiki-anchor">¶</a></h2>
<p>I'm developing Readline compatible library by pure Ruby implementation for Ruby core.<br>
<a href="https://github.com/aycabta/reline" class="external">https://github.com/aycabta/reline</a></p>
<p>I'm discussing it with <a class="user active user-mention" href="https://bugs.ruby-lang.org/users/572">@hsbt (Hiroshi SHIBATA)</a>, and I think that the pure Ruby version should be used only when the native extension version doesn't exist.<br>
ref. <a href="https://bugs.ruby-lang.org/issues/11084" class="external">https://bugs.ruby-lang.org/issues/11084</a><br>
The Readline library is very important for that IRB <em>always</em> provides Readline's features.<br>
So display width method is needed by Ruby core.</p>
<a name="Implementation-approach"></a>
<h2 >Implementation approach<a href="#Implementation-approach" class="wiki-anchor">¶</a></h2>
<a name="Uses-the-official-data-table"></a>
<h3 >Uses the official data table<a href="#Uses-the-official-data-table" class="wiki-anchor">¶</a></h3>
<p>Unicode Consortium provides display width data as "EastAsianWidth.txt".<br>
<a href="http://www.unicode.org/Public/10.0.0/ucd/EastAsianWidth.txt" class="external">http://www.unicode.org/Public/10.0.0/ucd/EastAsianWidth.txt</a></p>
<p>This name is based on historical reasons.<br>
This table is not exclusively for East Asian's characters in the present day, for example, Emoji.</p>
<a name="Uses-new-Regexp-feature-work-in-progress"></a>
<h3 >Uses new Regexp feature (work in progress)<a href="#Uses-new-Regexp-feature-work-in-progress" class="wiki-anchor">¶</a></h3>
<p>I propose new Unicode properties for Onigmo like Perl's one.<br>
<a href="https://github.com/k-takata/Onigmo/pull/102" class="external">https://github.com/k-takata/Onigmo/pull/102</a></p>
<p>I think that this is a better approach if the proposal for Onigmo is merged because String#grapheme_clusters what is based on Unicode specification uses Onigmo's feature inside.</p>
<a name="Cases-of-other-languages-or-libraries"></a>
<h2 >Cases of other languages or libraries<a href="#Cases-of-other-languages-or-libraries" class="wiki-anchor">¶</a></h2>
<p>Python: unicodedata.east_asian_width (standard library)<br>
<a href="https://docs.python.org/3.6/library/unicodedata.html#unicodedata.east_asian_width" class="external">https://docs.python.org/3.6/library/unicodedata.html#unicodedata.east_asian_width</a></p>
<p>Perl: "East_Asian_Width: *" of Unicode properties (regular expression in language)<br>
<a href="https://perldoc.perl.org/perluniprops.html" class="external">https://perldoc.perl.org/perluniprops.html</a></p>
<p>Go: golang.org/x/text/width<br>
<a href="https://godoc.org/golang.org/x/text/width" class="external">https://godoc.org/golang.org/x/text/width</a></p>
<p>PHP: mb_strwidth (standard library)<br>
<a href="http://php.net/manual/en/function.mb-strwidth.php" class="external">http://php.net/manual/en/function.mb-strwidth.php</a></p>
<p>JavaScript: eastasianwidth (npm library)<br>
<a href="https://www.npmjs.com/package/eastasianwidth" class="external">https://www.npmjs.com/package/eastasianwidth</a></p>
<p>RubyGems: unicode-display_width gem<br>
<a href="https://rubygems.org/gems/unicode-display_width" class="external">https://rubygems.org/gems/unicode-display_width</a></p> Ruby master - Feature #14593 (Open): Add `Enumerator#concat`https://bugs.ruby-lang.org/issues/145932018-03-08T15:37:38Zskalee (Sebastian Skalacki)skalee@gmail.com
<p>I propose introducing an <code>Enumerator#concat(other_enum1, other_enum2, ...)</code> which returns an enumerator being a concatenation of <code>self</code> and passed arguments.</p>
<a name="Expectation"></a>
<h2 >Expectation<a href="#Expectation" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">enum1</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">].</span><span class="nf">each</span>
<span class="n">enum2</span> <span class="o">=</span> <span class="sx">%w[a b c]</span><span class="p">.</span><span class="nf">each</span>
<span class="n">enum3</span> <span class="o">=</span> <span class="sx">%i[X Y Z]</span><span class="p">.</span><span class="nf">each</span>
<span class="n">concatenation</span> <span class="o">=</span> <span class="n">enum1</span><span class="p">.</span><span class="nf">concat</span><span class="p">(</span><span class="n">enum2</span><span class="p">,</span> <span class="n">enum3</span><span class="p">)</span>
<span class="n">concatenation</span><span class="p">.</span><span class="nf">kind_of?</span><span class="p">(</span><span class="no">Enumerator</span><span class="p">)</span>
<span class="c1">#=> true</span>
<span class="n">concatenation</span><span class="p">.</span><span class="nf">to_a</span>
<span class="c1">#=> [1, 2, 3, "a", "b", "c", :X, :Y, :Z]</span>
<span class="n">concatenation</span><span class="p">.</span><span class="nf">size</span>
<span class="c1">#=> 9</span>
<span class="n">enum_without_size</span> <span class="o">=</span> <span class="no">Enumerator</span><span class="p">.</span><span class="nf">new</span> <span class="p">{}</span>
<span class="n">enum_without_size</span><span class="p">.</span><span class="nf">size</span>
<span class="c1">#=> nil</span>
<span class="n">concatenation2</span> <span class="o">=</span> <span class="n">enum1</span><span class="p">.</span><span class="nf">concat</span><span class="p">(</span><span class="n">enum2</span><span class="p">,</span> <span class="n">enum_without_size</span><span class="p">,</span> <span class="n">enum3</span><span class="p">)</span>
<span class="n">concatenation2</span><span class="p">.</span><span class="nf">kind_of?</span><span class="p">(</span><span class="no">Enumerator</span><span class="p">)</span>
<span class="c1">#=> true</span>
<span class="n">concatenation2</span><span class="p">.</span><span class="nf">to_a</span>
<span class="c1">#=> [1, 2, 3, "a", "b", "c", :X, :Y, :Z]</span>
<span class="n">concatenation2</span><span class="p">.</span><span class="nf">size</span>
<span class="c1">#=> nil</span>
</code></pre>
<a name="Reasoning"></a>
<h2 >Reasoning<a href="#Reasoning" class="wiki-anchor">¶</a></h2>
<p>Enumerators are generally useful. They allow to iterate over some data set without loading them fully into memory. They help separating data generation from its consumption. If enumerators are desirable, then enumerator concatenation is desirable as well.</p>
<a name="Reference-implementation"></a>
<h2 >Reference implementation<a href="#Reference-implementation" class="wiki-anchor">¶</a></h2>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Enumerator</span>
<span class="k">def</span> <span class="nf">concat</span><span class="p">(</span><span class="o">*</span><span class="n">enums</span><span class="p">)</span>
<span class="n">enumerators</span> <span class="o">=</span> <span class="p">[</span><span class="nb">self</span><span class="p">,</span> <span class="o">*</span><span class="n">enums</span><span class="p">]</span>
<span class="n">size</span> <span class="o">=</span> <span class="n">enumerators</span><span class="p">.</span><span class="nf">reduce</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">acc</span><span class="p">,</span> <span class="n">enum</span><span class="o">|</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">enum</span><span class="p">.</span><span class="nf">size</span>
<span class="k">break</span> <span class="kp">nil</span> <span class="k">unless</span> <span class="n">s</span>
<span class="n">acc</span> <span class="o">+</span> <span class="n">s</span>
<span class="k">end</span>
<span class="no">Enumerator</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">size</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">y</span><span class="o">|</span>
<span class="n">enumerators</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">enum</span><span class="o">|</span>
<span class="n">enum</span><span class="p">.</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">item</span><span class="o">|</span> <span class="n">y</span> <span class="o"><<</span> <span class="n">item</span> <span class="p">}</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<a name="Flat-map-one-liner"></a>
<h2 >Flat map one-liner<a href="#Flat-map-one-liner" class="wiki-anchor">¶</a></h2>
<p>There's an answer on Stack Overflow suggesting a neat one-liner – <a href="https://stackoverflow.com/a/38962951/304175" class="external">https://stackoverflow.com/a/38962951/304175</a></p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">enums</span><span class="p">.</span><span class="nf">lazy</span><span class="p">.</span><span class="nf">flat_map</span><span class="p">{</span><span class="o">|</span><span class="n">enum</span><span class="o">|</span> <span class="n">enum</span><span class="p">.</span><span class="nf">lazy</span> <span class="p">}</span>
</code></pre>
<p>It yields items correctly. However, it is not very idiomatic. Neither it implements <code>#size</code> method properly (see example below). For these reasons, I think that implementing <code>Enumerator#concat</code> is a better option.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">enums</span> <span class="o">=</span> <span class="p">[</span><span class="n">enum1</span><span class="p">,</span> <span class="n">enum2</span><span class="p">,</span> <span class="n">enum3</span><span class="p">]</span>
<span class="c1">#=> [#<Enumerator: [1, 2, 3]:each>, #<Enumerator: ["a", "b", "c"]:each>, #<Enumerator: [:X, :Y, :Z]:each>]</span>
<span class="n">concatenation3</span> <span class="o">=</span> <span class="n">enums</span><span class="p">.</span><span class="nf">lazy</span><span class="p">.</span><span class="nf">flat_map</span><span class="p">{</span><span class="o">|</span><span class="n">enum</span><span class="o">|</span> <span class="n">enum</span><span class="p">.</span><span class="nf">lazy</span> <span class="p">}</span>
<span class="c1">#=> #<Enumerator::Lazy: #<Enumerator::Lazy: [#<Enumerator: [1, 2, 3]:each>, #<Enumerator: ["a", "b", "c"]:each>, #<Enumerator: [:X, :Y, :Z]:each>]>:flat_map></span>
<span class="n">concatenation3</span><span class="p">.</span><span class="nf">to_a</span>
<span class="c1">#=> [1, 2, 3, "a", "b", "c", :X, :Y, :Z]</span>
<span class="n">concatenation3</span><span class="p">.</span><span class="nf">size</span>
<span class="c1">#=> nil</span>
</code></pre>
<a name="Example-use-cases"></a>
<h2 >Example use cases<a href="#Example-use-cases" class="wiki-anchor">¶</a></h2>
<p>Process 20 tweets/posts without fetching more than needed. Generate some example posts if less than 20 is available</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">enum_tweets</span> <span class="o">=</span> <span class="n">lazy_fetch_tweets_from_twitter</span><span class="p">(</span><span class="ss">count: </span><span class="mi">20</span><span class="p">)</span>
<span class="c1">#=> Enumerator</span>
<span class="n">enum_fb_posts</span> <span class="o">=</span> <span class="n">lazy_fetch_posts_from_facebook</span><span class="p">(</span><span class="ss">count: </span><span class="mi">20</span><span class="p">)</span>
<span class="c1">#=> Enumerator</span>
<span class="n">enum_example_posts</span> <span class="o">=</span> <span class="no">Enumerator</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="o">|</span><span class="n">y</span><span class="o">|</span> <span class="kp">loop</span> <span class="p">{</span> <span class="n">y</span> <span class="o"><<</span> <span class="n">generate_random_post</span> <span class="p">}</span> <span class="p">}</span>
<span class="c1">#=> Enumerator</span>
<span class="n">posts</span> <span class="o">=</span> <span class="n">enum_tweets</span><span class="p">.</span><span class="nf">concat</span><span class="p">(</span><span class="n">enum_fb_posts</span><span class="p">).</span><span class="nf">concat</span><span class="p">(</span><span class="n">enum_example_posts</span><span class="p">).</span><span class="nf">take</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
<span class="n">process</span><span class="p">(</span><span class="n">posts</span><span class="p">)</span>
</code></pre>
<p>Perform a table union on large CSV files</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">csv1_enum</span> <span class="o">=</span> <span class="no">CSV</span><span class="p">.</span><span class="nf">foreach</span><span class="p">(</span><span class="s2">"path/to/1.csv"</span><span class="p">)</span>
<span class="n">csv2_enum</span> <span class="o">=</span> <span class="no">CSV</span><span class="p">.</span><span class="nf">foreach</span><span class="p">(</span><span class="s2">"path/to/2.csv"</span><span class="p">)</span>
<span class="n">csv1_enum</span><span class="p">.</span><span class="nf">concat</span><span class="p">(</span><span class="n">csv2_enum</span><span class="p">).</span><span class="nf">detect</span> <span class="p">{</span> <span class="o">|</span><span class="n">row</span><span class="o">|</span> <span class="n">is_what_we_are_looking_for?</span><span class="p">(</span><span class="n">row</span><span class="p">)</span> <span class="p">}</span>
</code></pre> Ruby master - Feature #14476 (Assigned): Adding same_all? for checking whether all items in an Ar...https://bugs.ruby-lang.org/issues/144762018-02-14T15:41:30Zmrkn (Kenta Murata)muraken@gmail.com
<p>In this issue, I propose to introduce <code>same_all?</code> instance method of <code>Array</code> class. This new method checks whether all items in the receiver are the same.</p>
<p>Today, I needed to write a code to judge whether all items in an <code>Array</code> are the same. I wanted to make the following expression, which I've written first, more efficient.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span> <span class="p">}</span>
</code></pre>
<p>I considered about the following simpler case, too.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">}</span>
</code></pre>
<p>As I discussed with some CRuby committers and my colleagues at Speee, Inc., I found that both cases can be written more efficiently as follows:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># for the 1st case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span><span class="p">.</span><span class="nf">yield_self</span> <span class="p">{</span><span class="o">|</span><span class="n">e0</span><span class="o">|</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">].</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">e0</span> <span class="p">}</span> <span class="p">}</span><span class="err"> </span>
<span class="c1"># for the 2nd case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="o">..-</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">]</span>
</code></pre>
<p>However, it is not easy to understand the intent of either expression, which is to check whether all items are the same.</p>
<p>I want to give this feature a clear name to make code readable. And I think it should be provided as a core feature because it can be made more efficient by being implemented in C language.</p>
<p>The benchmark script is: <a href="https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5" class="external">https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5</a><br>
I used it to find the efficient expressions. The example result of this benchmark on my MacBook Pro is here.</p>
<pre><code>$ ruby -v bench.rb
ruby 2.6.0dev (2018-02-14 trunk 62402) [x86_64-darwin16]
----------------------------------------
Benchmark case: shuffle
user system total real
all?-method-1 0.001525 0.000088 0.001613 ( 0.001632)
all?-method-2 0.000489 0.000031 0.000520 ( 0.000565)
all?-method-3 0.000444 0.000039 0.000483 ( 0.000482)
all?-item 0.000325 0.000078 0.000403 ( 0.000402)
opt-method 0.655959 0.033814 0.689773 ( 0.708515)
opt-item 0.000316 0.000001 0.000317 ( 0.000317)
----------------------------------------
Benchmark case: tail0
user system total real
all?-method-1 9.412810 0.231126 9.643936 ( 9.681118)
all?-method-2 5.375075 0.137908 5.512983 ( 5.754550)
all?-method-3 5.226132 0.167640 5.393772 ( 5.507031)
all?-item 0.873700 0.007545 0.881245 ( 0.917210)
opt-method 5.319648 0.172547 5.492195 ( 5.633140)
opt-item 0.174349 0.001974 0.176323 ( 0.183002)
----------------------------------------
Benchmark case: head0
user system total real
all?-method-1 0.002421 0.000068 0.002489 ( 0.002489)
all?-method-2 0.002169 0.000213 0.002382 ( 0.002382)
all?-method-3 0.001624 0.000026 0.001650 ( 0.001651)
all?-item 0.000623 0.000001 0.000624 ( 0.000624)
opt-method 4.779120 0.146312 4.925432 ( 4.951167)
opt-item 0.000629 0.000001 0.000630 ( 0.000629)
----------------------------------------
Benchmark case: all1
user system total real
all?-method-1 9.379650 0.255865 9.635515 ( 9.683078)
all?-method-2 4.950280 0.150659 5.100939 ( 5.140174)
all?-method-3 4.857898 0.129125 4.987023 ( 5.003142)
all?-item 0.694113 0.001295 0.695408 ( 0.702370)
opt-method 5.032373 0.121708 5.154081 ( 5.189599)
opt-item 0.170540 0.002069 0.172609 ( 0.180343)
</code></pre> Ruby master - Feature #14404 (Open): Adding writev support to IO#write_nonblockhttps://bugs.ruby-lang.org/issues/144042018-01-26T11:12:00Zjanko (Janko Marohnić)janko@hey.com
<p>In Ruby 2.5 IO#write received writev support (<a href="https://github.com/ruby/ruby/commit/3efa7126e5e853f06cdd78d4d88837aeb72a9a3e" class="external">https://github.com/ruby/ruby/commit/3efa7126e5e853f06cdd78d4d88837aeb72a9a3e</a>), allowing it to accept multiple arguments and utilize writev when available.</p>
<p>Would it be possible to add this feature to IO#write_nonblock as well? IO#write_nonblock is used by the HTTP.rb and Socketry gems to implement their "write timeout" feature (the same way that IO#read_nonblock is used in Net::HTTP to implement "read timeout"). Since IO#write_nonblock doesn't yet support writev, at the moment it's not possible for HTTP.rb and Socketry to utilize writev when the "write timeout" is specified.</p> Ruby master - Feature #14399 (Open): Add Enumerable#producthttps://bugs.ruby-lang.org/issues/143992018-01-24T23:30:36Zjzakiya (Jabari Zakiya)
<p>For similar reasons for creating <code>Enumerable#sum</code> a companion method<br>
<code>Enumerable#product</code> is also very useful. Taking the product of<br>
numbers in arrays is a common operation in many numerical algorithms,<br>
especially in number theory and cryptography, and its optimization in<br>
Ruby will make it more conducive to math heavy algorithms and tasks.</p>
<p>This</p>
<pre><code>> [2,3,5,7].reduce(:*) => 210
</code></pre>
<p>can be optimized to this</p>
<pre><code>> [2,3,5,7].product => 210
</code></pre>
<p>It should also allow an initial value</p>
<pre><code>> [2,3,5,7].product(2) => 420
> [2,3,5,7].product(0.5) => 105
</code></pre>
<p>Crystal already has this <code>method</code>.</p> Ruby master - Feature #14122 (Open): Add LogicErrorhttps://bugs.ruby-lang.org/issues/141222017-11-21T02:19:15Zeike.rb (Eike Dierks)eike@inter.net
<p>Dear friends at ruby</p>
<p>I'd like to suggest a new error for ruby-core: LogicError</p>
<p>That error should be thrown<br>
upon operations that are detected to be illogic or impossible by semantics.<br>
I believe that this could improve the error messages a lot.</p>
<p>Today we have:<br>
1.to_enum - 2.to_enum<br>
NoMethodError: undefined method `-' for #<Enumerator: 1:each></p>
<p>Well, there are good reasons why #- is not implemented for Enumerator,<br>
more so for (Enumerator - Enumerator)</p>
<p>Today this throws NoMethodError,<br>
while I'd like to throw this a LogicError,<br>
with an attached explanation,<br>
that this operation simply does not make any sense.</p>
<p>But then, we should simply mark this as reserved (like private def)</p>
<hr>
<p>I believe we can improve on the ease of using ruby<br>
if we improve on the error messages</p>
<p>For the kids: NoMethodError is not that friendly,<br>
(my kid tried to add and substract all and anything)</p>
<p>Don't get me wrong,<br>
I am well aware about NoMethodErrors<br>
(and how to reflect that on proxy APIs)</p>
<p>I'm asking for something different.</p>
<p>I want to explicitely raise a LogicError<br>
for that operations that make no sense.</p>
<hr>
<p>Alternate implementation:<br>
StandardError#explain<br>
because some of the errors that we detect can be explained.</p> Ruby master - Feature #14092 (Open): Add extension key argument to Tempfilehttps://bugs.ruby-lang.org/issues/140922017-11-08T11:46:36ZTheSmartnik (Nikita Misharin)
<p>I don't work with Tempfile often, but every time I do, I get surprised by an obscure way to pass an extension to file name.<br>
You have to pass array, where first element is a file name and a second is a file extension <em>(starting with a dot)</em>, which is quite a unique <em>(not in a good way)</em> and unusual interface for ruby.<br>
I think a much better interface would be to use a separate key word for this.</p>
<p>I've researched the code and it seems we can achieve that without changing much code. I can make pr, if you think the idea is worthy</p> Ruby master - Feature #14077 (Open): Add Encoding::FILESYSTEM and Encoding::LOCALE constantshttps://bugs.ruby-lang.org/issues/140772017-11-03T16:35:15Znirvdrum (Kevin Menard)
<p>The <code>Encoding</code> class has constants defined for all of the standard encodings, but does not have constants defined for some of the special encodings. In particular, the "filesystem" and "locale" encodings do not have a corresponding <code>Encoding::FILESYSTEM</code> and <code>Encoding::LOCALE</code>. As a result, every time they need to be used they must be looked up using <code>Encoding.find</code>. As far as I can tell, neither of these special encodings can change after the Ruby process has been started up. Even changing the <code>$LANG</code> environment variable within the Ruby process doesn't seem to affect the value for these special encodings.</p>
<p>Therefore, I'm proposing the introduction of <code>Encoding::FILESYSTEM</code> and <code>Encoding::LOCALE</code> constants both as a matter of consistency and as a matter of efficiency.</p> Ruby master - Feature #13924 (Open): Add headings/hints to RubyVM::InstructionSequence#disasmhttps://bugs.ruby-lang.org/issues/139242017-09-20T13:39:53Ztonytonyjan (Weihang Jian)tonytonyjan@gmail.com
<p>As the official document mentions, this method will return a String with the human readable instructions. However, it is quite hard to read since we can not understand the definition of each column, for example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">puts</span> <span class="no">RubyVM</span><span class="o">::</span><span class="no">InstructionSequence</span><span class="p">.</span><span class="nf">compile</span><span class="p">(</span><span class="s2">"[4, 5].max"</span><span class="p">).</span><span class="nf">disasm</span>
<span class="o">==</span> <span class="ss">disasm: </span><span class="c1">#<ISeq:<compiled>@<compiled>>================================</span>
<span class="mo">0000</span> <span class="n">trace</span> <span class="mi">1</span> <span class="p">(</span> <span class="mi">1</span><span class="p">)</span>
<span class="mo">0002</span> <span class="n">duparray</span> <span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="mo">0004</span> <span class="n">opt_send_without_block</span> <span class="o"><</span><span class="n">callinfo!mid</span><span class="ss">:max</span><span class="p">,</span> <span class="n">argc</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span> <span class="no">ARGS_SIMPLE</span><span class="o">></span><span class="p">,</span> <span class="o"><</span><span class="n">callcache</span><span class="o">></span>
<span class="mo">0007</span> <span class="n">leave</span>
</code></pre>
<p>There is no clue can inform us that "( 1)" stands for the line number, is it possible to either improve documentation or add some hints to the output string?</p> Ruby master - Feature #13893 (Open): Add Fiber#[] and Fiber#[]= and restore Thread#[] and Thread#...https://bugs.ruby-lang.org/issues/138932017-09-12T13:54:59Zcremes (Chuck Remes)
<p>Ruby 3 API cleanup suggestion.</p>
<p>The Thread and Fiber classes have a very odd API for setting/getting thread local and fiber local variables. With Ruby 3 coming soon, this is a perfect opportunity to make this API more coherent and return to the Principal of Least Surprise. The concept of Fibers and Threads should be completely separated and we should no longer assume that a Fiber is attached to any particular Thread.</p>
<p>I suggest this:</p>
<pre><code>class Fiber
# Gets a fiber-local variable.
def [](index)
...
end
# Sets a fiber-local variable.
def []=(index, value)
...
end
# Returns true if the given +key+ exists as a fiber-local variable.
def key?(key)
...
end
# Returns an array of fiber-local variable names as symbols.
def keys
...
end
end
class Thread
# Gets a thread-local variable.
def [](index)
...
end
# Sets a thread-local variable.
def []=(index, value)
...
end
# Returns true if the given +key+ exists as a thread-local variable.
def key?(key)
...
end
# Returns an array of thread-local variable names as symbols.
def keys
...
end
end
</code></pre>
<p>Also, remove <code>Thread#thread_variable?</code>, <code>Thread#thread_variable_get</code>, <code>Thread#variable_set</code>, and <code>Thread#thread_variables</code> since that behavior is already covered by <code>Thread#key?</code>, <code>Thread#keys</code>, <code>Thread#[]</code>, and <code>Thread#[]=</code>. The APIs for both Thread and Fiber are more coherent and less surprising with these changes.</p> Ruby master - Feature #13820 (Open): Add a nil coalescing operatorhttps://bugs.ruby-lang.org/issues/138202017-08-16T10:50:01Zwilliamn (William Newbery)
<p>It would be nice if Ruby had an operator that only considered <code>nil</code> as false, like the null coalescing operators or "Logical Defined-Or operator" (Perl) found in some other languages. Ive seen things like <code>//</code> and <code>//=</code>m <code>??</code> and <code>??=</code>, or <code>?:</code> used for this.</p>
<p>This would work like <code>||</code> and <code>||=</code> for short circuiting etc. except that only <code>nil</code> is considered a false condition.</p>
<p>While Ruby considers only "false" and "nil" as false, with everything else true ("", [], {}, etc.) I still find occasionally people trip up when using logical or, <code>||</code> and <code>||=</code> when the value may be false.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">||</span> <span class="mi">55</span> <span class="c1"># = 0 Ruby already considers 0, "", etc. as true (oter languages do differ a lot here)</span>
<span class="n">a</span> <span class="o">=</span> <span class="mi">0</span> <span class="p">??</span> <span class="mi">55</span> <span class="c1"># = 0 So no change here</span>
<span class="n">a</span> <span class="o">=</span> <span class="kp">nil</span> <span class="o">||</span> <span class="mi">55</span> <span class="c1"># = 55, nil is false so right side is evaulated.</span>
<span class="n">a</span> <span class="o">=</span> <span class="kp">nil</span> <span class="sc">??</span> <span class="mi">55</span> <span class="c1"># = 55, again no change</span>
<span class="n">a</span> <span class="o">=</span> <span class="kp">false</span> <span class="o">||</span> <span class="mi">55</span> <span class="c1"># = 55, however false is false for logical or</span>
<span class="n">a</span> <span class="o">=</span> <span class="kp">false</span> <span class="sc">??</span> <span class="mi">55</span> <span class="c1"># = false, but its still a non-nil value</span>
</code></pre>
<p>For example when doing things like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">lazy</span>
<span class="vi">@lazy</span> <span class="o">||=</span> <span class="n">compute_this</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">fetch</span><span class="p">(</span><span class="nb">id</span><span class="p">,</span> <span class="o">**</span><span class="n">opts</span><span class="p">)</span>
<span class="n">host</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="ss">:host</span><span class="p">]</span> <span class="o">||</span> <span class="n">default_host</span>
<span class="n">https</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="ss">:https</span><span class="p">]</span> <span class="o">||</span> <span class="kp">true</span>
<span class="n">port</span> <span class="o">=</span> <span class="n">opts</span><span class="p">[</span><span class="ss">:port</span><span class="p">]</span> <span class="o">||</span> <span class="p">(</span><span class="n">https</span> <span class="p">?</span> <span class="mi">443</span> <span class="p">:</span> <span class="mi">80</span><span class="p">)</span>
<span class="o">...</span>
</code></pre>
<p>Normally the intention is to use a default value or compute an action if no value is provided, which if the value may be false then requires special handling, or sometimes is missed and results in a bug.</p> Ruby master - Feature #13696 (Assigned): Add exchange and noreplace options to File.renamehttps://bugs.ruby-lang.org/issues/136962017-06-29T03:07:38ZGlass_saga (Masaki Matsushita)glass.saga@gmail.com
<p>renameat2(2) introduced in linux kernel 3.15 takes following flags.</p>
<pre><code>RENAME_EXCHANGE: Atomically exchange oldpath and newpath.
RENAME_NOREPLACE: Don't overwrite newpath of the rename. Return an error if newpath already exists.
</code></pre>
<p>This change makes <code>File.rename</code> take these flags as keyword arguments.</p>
<p>Example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">File</span><span class="p">.</span><span class="nf">write</span><span class="p">(</span><span class="s2">"hoge"</span><span class="p">,</span> <span class="s2">"hoge"</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="s2">"fuga"</span><span class="p">,</span> <span class="s2">"fuga"</span><span class="p">)</span>
<span class="no">File</span><span class="p">.</span><span class="nf">rename</span><span class="p">(</span><span class="s2">"hoge"</span><span class="p">,</span> <span class="s2">"fuga"</span><span class="p">,</span> <span class="ss">exchange: </span><span class="kp">true</span><span class="p">)</span> <span class="c1"># atomically exchanged</span>
<span class="no">File</span><span class="p">.</span><span class="nf">read</span><span class="p">(</span><span class="s2">"fuga"</span><span class="p">)</span> <span class="c1">#=> "hoge"</span>
<span class="no">File</span><span class="p">.</span><span class="nf">rename</span><span class="p">(</span><span class="s2">"hoge"</span><span class="p">,</span> <span class="s2">"fuga"</span><span class="p">,</span> <span class="ss">noreplace: </span><span class="kp">true</span><span class="p">)</span> <span class="c1">#=> File exists @ syserr_fail2_in - fuga (Errno::EEXIST)</span>
</code></pre> Ruby master - Feature #13395 (Open): Add a method to check for not nilhttps://bugs.ruby-lang.org/issues/133952017-04-01T20:24:14ZJustJosh (Joshua Stowers)
<p>There does not seem to be a method in Ruby to check if an object is <em>not</em> nil.<br>
Such a method could help with readability.</p>
<p>Example:</p>
<blockquote>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'dog'</span><span class="p">,</span> <span class="kp">nil</span><span class="p">]</span>
<span class="n">array</span><span class="p">.</span><span class="nf">count</span><span class="p">(</span><span class="o">&</span><span class="ss">:not_nil?</span><span class="p">)</span>
</code></pre>
</blockquote>
<blockquote>
<p>vs</p>
</blockquote>
<blockquote>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">array</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'dog'</span><span class="p">,</span> <span class="kp">nil</span><span class="p">]</span>
<span class="n">array</span><span class="p">.</span><span class="nf">reject</span><span class="p">(</span><span class="o">&</span><span class="ss">:nil?</span><span class="p">).</span><span class="nf">count</span>
</code></pre>
</blockquote> Ruby master - Feature #13263 (Open): Add companion integer nth-root method to recent Integer#isqrthttps://bugs.ruby-lang.org/issues/132632017-02-28T21:01:42Zjzakiya (Jabari Zakiya)
<p>Following the heels of adding the method <code>Integer#isqrt</code>, to create exact integer<br>
squareroot values for arbitrary sized integers, based on the following threads:</p>
<p><a href="https://bugs.ruby-lang.org/issues/13219" class="external">https://bugs.ruby-lang.org/issues/13219</a><br>
<a href="https://bugs.ruby-lang.org/issues/13250" class="external">https://bugs.ruby-lang.org/issues/13250</a></p>
<p>I also request adding its companion method to compute any integer nth-root too.</p>
<p>Below are sample methods of high level Ruby code that compute exact results.</p>
<p><a href="https://en.wikipedia.org/wiki/Nth_root_algorithm" class="external">https://en.wikipedia.org/wiki/Nth_root_algorithm</a></p>
<p>The Newton's code is a Python version I tweaked to make it look like <code>Integer#isqrt</code>'s form.</p>
<p>Benchmarks show the <strong>bbm</strong> method is generally faster, especially as the roots become larger,<br>
than using Newton's method, with an added benefits its simpler to code/understand, and has a lower<br>
sensitivity to the initial root value, and handling of small numbers.</p>
<pre><code>class Integer
def irootn(n) # binary bit method (bbm) for nth root
return nil if self < 0 && n.even?
raise "root n is < 2 or not an Integer" unless n.is_a?(Integer) && n > 1
num = self.abs
bits_shift = (num.bit_length - 1)/n + 1 # add 1 for initial loop >>= 1
root, bitn_mask = 0, (1 << bits_shift)
until (bitn_mask >>= 1) == 0
root |= bitn_mask
root ^= bitn_mask if root**n > num
end
root *= self < 0 ? -1 : 1
end
def irootn1(n) # Newton's method for nth root
return nil if self < 0 && n.even?
raise "root n is < 2 or not an Integer" unless n.is_a?(Integer) && n > 1
return self if self == 0 || (self == -1 && n.odd?)
num = self.abs
b = num.bit_length
e, u, x = n-1, (x = 1 << (b-1)/(n-1)), x+1
while u < x
x = u
t = e * x + num / x ** e
u = t / n
end
x *= self < 0 ? -1 : 1
end
def irootn2(n) # Newton's restructured coded method for nth root
return nil if self < 0 && n.even?
raise "root n is < 2 or not an Integer" unless n.is_a?(Integer) && n > 1
return self if self == 0 || (self == -1 && n.odd?)
num = self.abs
b = num.bit_length
e, x = n-1, 1 << (b-1)/(n-1) + 1
while t = (e * x + num / x ** e)/n < x
x = (e * x + num / x ** e)/n
end
x *= self < 0 ? -1 : 1
end
end
require "benchmark/ips"
[50, 500, 1000, 2000, 4000, 5000].each do |exp|
[3, 4, 7, 13, 25, 33]. each do |k|
Benchmark.ips do |x|
n = 10**exp
puts "integer root tests for root #{k} of n = 10**#{exp}"
x.report("bbm" ) { n.irootn(k) }
x.report("newton1" ) { n.irootn1(k) }
x.report("newton2" ) { n.irootn2(k) }
x.compare!
end
end
end
</code></pre>
<p>Here are results.</p>
<pre><code>def tm; t=Time.now; yield; Time.now-t end
2.4.0 :022 > exp = 111; n = 10**exp; r = 10; puts n, "#{ tm{ puts n.irootn(r)} }", "#{ tm{ puts n.irootn1(r)} }", "#{ tm{ puts n.irootn2(r)} }"
125892541179
125892541179
125892541179
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
4.6673e-05
6.5506e-05
0.000121357
=> nil
2.4.0 :023 > exp = 150; n = 10**exp; r = 50; puts n, "#{tm{ puts n.irootn(r)}}", "#{ tm{ puts n.irootn1(r)}}", "#{ tm{ puts n.irootn2(r)} }"
1000
1000
1000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
2.28e-05
1.8762e-05
0.000128852
=> nil
2.4.0 :024 >
</code></pre>
<p>The benchmarks show that <code>irootn2</code> is the slowest but it has the same<br>
form as <code>Integer#isqt</code> in the numeric.c and bignum.c files in trunk.<br>
It probably can be tweaked to make it faster.</p>
<p>bignum.c, starting at line 6772<br>
<a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/57705/entry/bignum.c" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/57705/entry/bignum.c</a><br>
numeric.c, starting at line 5131<br>
<a href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/57705/entry/numeric.c" class="external">https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/57705/entry/numeric.c</a></p>
<p>Thus, a hybrid method could be created that swtiches between the two.</p>
<pre><code>def isqrt(num=self)
b = num.bit_length
x = 1 << (b-1)/2 | num >> (b/2 + 1) # optimum first root extimate
while (t = num / x) < x
x = ((x + t) >> 1)
end
x
end
def irootn2(n)
b = num.bit_length
e, x = n-1, 1 << (b-1)/(n-1) + 1 # optimum first root estimate(?)
while t = (e * x + num / x ** e)/n < x
x = (e * x + num / x ** e)/n
end
x
end
def irtn(n) # possible hybrid combination for all nth-roots
b = num.bit_length
if 2 < n # for squareroot
x = 1 << (b-1)/2 | num >> (b/2 + 1)
while (t = num / x) < x
x = ((x + t) >> 1)
end
else # for roots > 2
e, x = n-1, 1 << (b-1)/(n-1) + 1
while t = (e * x + num / x ** e)/n < x
x = (e * x + num / x ** e)/n
end
end
x *= if self < 0 ? -1 : 1
end
</code></pre>
<p>So with just a little more work, a highly performant nth-root method can be added<br>
to the std lib, as with <code>Integer#isqrt</code>, to take care of all the exact integer roots<br>
for arbitrary sized integers, by whatever name that is preferable.</p>
<p>This will enhance Ruby's use even more in fields like number theory, advanced math, cryptography,<br>
etc, to have fast primitive standard methods to compute these use case values.</p> Ruby master - Feature #12867 (Open): Add ability to check validity of a URLhttps://bugs.ruby-lang.org/issues/128672016-10-23T06:53:20Zshlok007 (Shlok Srivastava)shlok.srivastava15@gmail.com
<p>Hi!<br>
Going through the URI module of Ruby, it was obvious that we can check the validity of a URI by using URI.regexp . However, I found out there is no way we can accurately check for a valid URL by using the URI module. Won't it be better if there was a built in method in the URI module that could check for the validity of a URL or a URN as well ?</p>
<p>This is just a suggestion and feel free to close it if this doesn't seems like something that should be implemented. :)</p>
<p>PS- If you feel this can or should be implemented, I would love to work on it. ;)<br>
Thank you.</p> Ruby master - Feature #12802 (Open): Add BLAKE2 support to Digesthttps://bugs.ruby-lang.org/issues/128022016-10-01T17:49:01Zbascule (Tony Arcieri)bascule@gmail.com
<p>BLAKE2 is a fast, modern hash function, based on improvements to the BLAKE function, which was a SHA3 finalist. BLAKE2 performs about twice as fast in software as SHA3 winner Keccak:</p>
<p><a href="https://blake2.net/" class="external">https://blake2.net/</a></p>
<p>BLAKE2 has received an informational RFC 7693 from the IETF:</p>
<p><a href="https://tools.ietf.org/html/rfc7693" class="external">https://tools.ietf.org/html/rfc7693</a></p>
<p>It was added to the Python standard library in Python 3.6:</p>
<p><a href="https://docs.python.org/3.6/library/hashlib-blake2.html" class="external">https://docs.python.org/3.6/library/hashlib-blake2.html</a></p>
<p>If there's interest in supporting BLAKE2 in the Ruby standard library, I can put together a patch.</p> Ruby master - Feature #12455 (Open): Add a way for class String to determine whether it has only ...https://bugs.ruby-lang.org/issues/124552016-06-02T16:37:18Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hello.</p>
<p>Not sure if that has been suggested before. If it was and not deemed fit,<br>
please feel free to close this issue request here.</p>
<p>For class String, would it be possible to find out if a given String<br>
contains only numbers, without having to do a regex check?</p>
<pre><code>x = '123'
</code></pre>
<p>A regex will do of course:</p>
<pre><code>if x =~ /^\d+$/
</code></pre>
<p>I was wondering if we could have a method that does something similar,<br>
that is also easier to read.</p>
<p>Something like:</p>
<pre><code>x = '123'
x.only_numbers?
</code></pre>
<p>or</p>
<pre><code>x.only_digits?
</code></pre>
<p>Something like that.</p>
<p>I do not know whether the word "only" is good or not. Perhaps ".all_numbers?"<br>
or ".all_digits?" would be better. But the name is secondary probably, more<br>
important would be whether such a method would make sense for class String.</p>
<p>I am more interested in a method that will help avoid the use of a regex here.</p>
<p>The method should return true if the string has only numbers, and false<br>
otherwise.</p>
<p>Anyway, thanks for reading!</p> Ruby master - Feature #12272 (Open): Accepting HTML entity name in string literalhttps://bugs.ruby-lang.org/issues/122722016-04-12T13:00:03Zsawa (Tsuyoshi Sawada)
<p>String literal allows the escape character <code>\u</code> to describe a character using UTF-8 character code like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="s2">"</span><span class="se">\u</span><span class="s2">201c"</span> <span class="c1"># left double quote</span>
<span class="s2">"</span><span class="se">\u</span><span class="s2">2191"</span> <span class="c1"># up arrow</span>
</code></pre>
<p>This is useful in typing characters that are not easy to input from the keyboard. However, normal people do not memorize the UTF-8 codes by heart.</p>
<p>The HTML symbol entity name is the place where we can compromise (although it is not available for the entire UTF-8), I think. I would like the string literal to be extended to accept HTML entity names and interpret them as the corresponding UTF-8 characters. I do not have a definite idea for the syntax, but a candidate can be an escape character <code>\& ... ;</code>, so that we can type:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="s2">"</span><span class="se">\&</span><span class="s2">ldquo;"</span> <span class="c1"># left double quote</span>
<span class="s2">"</span><span class="se">\&</span><span class="s2">uarr;"</span> <span class="c1"># up arrow</span>
</code></pre>
<p>Currently, <code>"\&"</code> is interpreted as <code>"&"</code>, so this will be a compatibility breaking change, and if that is not desirable, perhaps a different syntax may be considered.</p> Ruby master - Feature #12247 (Open): accept multiple arguments at Array#deletehttps://bugs.ruby-lang.org/issues/122472016-04-03T08:51:28Zusa (Usaku NAKAMURA)usa@garbagecollect.jp
<p>I found that it's very useful if <code>Array#delete</code> accepts multiple arguments.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span> <span class="c1">#=> [1, 3]</span>
<span class="n">ary</span> <span class="c1">#=> [2, 4, 5]</span>
</code></pre> Ruby master - Feature #12244 (Assigned): 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 #11689 (Open): Add methods allow us to get visibility from Method and Unbou...https://bugs.ruby-lang.org/issues/116892015-11-15T04:53:31Zyui-knk (Kaneko Yuichiro)
<p>Add <code>Method#visibility</code> and <code>UnboundMethod#visibility</code> for getting visibility from Method and UnboundMethod object.<br>
In GitHub <a href="https://github.com/ruby/ruby/pull/1098" class="external">https://github.com/ruby/ruby/pull/1098</a>.</p> Ruby master - Feature #11597 (Open): Add Linux-specific setfsuid(2)/setfsgid(2)https://bugs.ruby-lang.org/issues/115972015-10-15T19:36:46Zvihai (Daniele Orlandi)daniele@orlandi.com
<p>I would be helpful if you add a binding to the Linux-specific syscalls</p>
<p>setfsuid(2)<br>
setfsgid(2)</p>
<p>Their purpose is to change the uid/gid with which filesystem access control is performed. Their main usage is simulating fs access on behalf of other users.</p>
<p>Differently from setuid/setreuid/etc... thess calls have thread-local effect, thus they may be useful in solving some problems when needing to temporarily drop privileges in multi-threaded applications.</p> Ruby master - Feature #11583 (Open): Add File#unlinkhttps://bugs.ruby-lang.org/issues/115832015-10-12T04:32:48Zksss (Yuki Kurihara)co000ri@gmail.com
<p>I propose new method <strong>File#unlink</strong>.</p>
<p><strong>File#unlink</strong> is same as <strong>Fille.unlink</strong> like this.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">File</span>
<span class="k">def</span> <span class="nf">unlink</span>
<span class="no">File</span><span class="p">.</span><span class="nf">unlink</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>It is more objective.<br>
And will be able to write duck typeing with <strong>Tempfile#unlink</strong></p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gd">- Tempfile.open do |f|
</span><span class="gi">+ Tempfile.create do |f|
</span> f.unlink # Not raise an error
<span class="p">end
</span></code></pre> Ruby master - Feature #11577 (Open): Add encodeURIComponent compatible API for URIhttps://bugs.ruby-lang.org/issues/115772015-10-09T13:40:10Znaruse (Yui NARUSE)naruse@airemix.jp
<p>How about adding encodeURIComponent/decodeURIComponent compatible API?</p>
<p>There's already have some methods:</p>
<ul>
<li>URI.escape: context aware but deprecated.</li>
<li>URIencode_www_form: application/x-www-form-urlencoded, which encodes spaces into '+'</li>
<li>URIencode_www_form_component: above component</li>
</ul>
<p>So it doesn't have non-form URI escape method.</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/lib/uri/common.rb b/lib/uri/common.rb
index 1444ae8..0017ae3 100644
</span><span class="gd">--- a/lib/uri/common.rb
</span><span class="gi">+++ b/lib/uri/common.rb
</span><span class="p">@@ -1,4 +1,5 @@</span>
<span class="gd">-#--
</span><span class="gi">+#
+# -*- frozen-string-literal: true -*-
</span> # = uri/common.rb
#
# Author:: Akira Yamada <akira@ruby-lang.org>
<span class="p">@@ -329,27 +330,72 @@</span> module URI
DEFAULT_PARSER.make_regexp(schemes)
end
<span class="gi">+ TBLENCURICOMP_ = {} # :nodoc:
</span> TBLENCWWWCOMP_ = {} # :nodoc:
<span class="gd">- 256.times do |i|
- TBLENCWWWCOMP_[i.chr] = '%%%02X' % i
- end
- TBLENCWWWCOMP_[' '] = '+'
- TBLENCWWWCOMP_.freeze
</span><span class="gi">+ TBLDECURICOMP_ = {} # :nodoc:
</span> TBLDECWWWCOMP_ = {} # :nodoc:
256.times do |i|
h, l = i>>4, i&15
<span class="gd">- TBLDECWWWCOMP_['%%%X%X' % [h, l]] = i.chr
- TBLDECWWWCOMP_['%%%x%X' % [h, l]] = i.chr
- TBLDECWWWCOMP_['%%%X%x' % [h, l]] = i.chr
- TBLDECWWWCOMP_['%%%x%x' % [h, l]] = i.chr
</span><span class="gi">+ c = i.chr.freeze
+ k = sprintf('%%%X%X', h, l).freeze
+ TBLENCURICOMP_[c] = TBLENCWWWCOMP_[c] = k
+ TBLDECURICOMP_[k] = TBLDECWWWCOMP_[k] = c
+ k = sprintf('%%%x%X', h, l).freeze
+ TBLDECURICOMP_[k] = TBLDECWWWCOMP_[k] = c
+ k = sprintf('%%%X%x', h, l).freeze
+ TBLDECURICOMP_[k] = TBLDECWWWCOMP_[k] = c
+ k = sprintf('%%%x%x', h, l).freeze
+ TBLDECURICOMP_[k] = TBLDECWWWCOMP_[k] = c
</span> end
<span class="gi">+ TBLENCWWWCOMP_[' '] = '+'
+ TBLENCWWWCOMP_.freeze
+ TBLENCURICOMP_.freeze
</span> TBLDECWWWCOMP_['+'] = ' '
TBLDECWWWCOMP_.freeze
<span class="gi">+ TBLDECURICOMP_.freeze
+
+ # Encode given +str+ to URL-encoded form data.
+ #
+ # This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
+ # (ASCII space) to + and converts others to %XX.
+ #
+ # If +enc+ is given, convert +str+ to the encoding before percent encoding.
+ #
+ # This is an implementation of
+ # http://www.ecma-international.org/ecma-262/6.0/#sec-encodeuricomponent-uricomponent
+ #
+ # See URI.encode_www_form_component, URI.encode_www_form
+ def self.encode_component(str)
+ str = str.to_s.dup
+ if !str.ascii_only?
+ enc = str.encoding
+ if enc != Encoding::ASCII_8BIT && enc != Encoding::UTF_8
+ str.encode!(Encoding::UTF_8, invalid: :replace, undef: :replace)
+ end
+ str.force_encoding(Encoding::ASCII_8BIT)
+ end
+ str.gsub!(/[^\-_.!~*'()0-9A-Za-z]/, TBLENCURICOMP_)
+ str.force_encoding(Encoding::US_ASCII)
+ end
+
+ # Decode given +str+ of URL-encoded form data.
+ #
+ #
+ # This doesn't decodes + to SP.
+ #
+ # This is an implementation of
+ # http://www.ecma-international.org/ecma-262/6.0/#sec-decodeuricomponent-encodeduricomponent
+ #
+ # See URI.decode_www_form_component, URI.decode_www_form
+ def self.decode_component(str, enc=Encoding::UTF_8)
+ raise ArgumentError, "invalid %-encoding (#{str})" if /%(?!\h\h)/ =~ str
+ str.b.gsub(/%\h\h/, TBLDECURICOMP_).force_encoding(enc)
+ end
</span>
HTML5ASCIIINCOMPAT = defined? Encoding::UTF_7 ? [Encoding::UTF_7, Encoding::UTF_16BE, Encoding::UTF_16LE,
Encoding::UTF_32BE, Encoding::UTF_32LE] : [] # :nodoc:
<span class="gd">- # Encode given +str+ to URL-encoded form data.
</span><span class="gi">+ # Encode given +str+ in application/x-www-form-urlencoded format.
</span> #
# This method doesn't convert *, -, ., 0-9, A-Z, _, a-z, but does convert SP
# (ASCII space) to + and converts others to %XX.
<span class="p">@@ -373,7 +419,7 @@</span> module URI
str.force_encoding(Encoding::US_ASCII)
end
<span class="gd">- # Decode given +str+ of URL-encoded form data.
</span><span class="gi">+ # Decode given +str+ in application/x-www-form-urlencoded format.
</span> #
# This decodes + to SP.
#
<span class="p">@@ -457,7 +503,7 @@</span> module URI
if isindex
if sep.empty?
val = key
<span class="gd">- key = ''
</span><span class="gi">+ key = String.new
</span> end
isindex = false
end
<span class="p">@@ -471,7 +517,7 @@</span> module URI
if val
val.gsub!(/\+|%\h\h/, TBLDECWWWCOMP_)
else
<span class="gd">- val = ''
</span><span class="gi">+ val = String.new
</span> end
ary << [key, val]
<span class="gh">diff --git a/test/uri/test_common.rb b/test/uri/test_common.rb
index 5620415..c6b5633 100644
</span><span class="gd">--- a/test/uri/test_common.rb
</span><span class="gi">+++ b/test/uri/test_common.rb
</span><span class="p">@@ -54,6 +54,34 @@</span> class TestCommon < Test::Unit::TestCase
assert_raise(NoMethodError) { Object.new.URI("http://www.ruby-lang.org/") }
end
<span class="gi">+ def test_encode_component
+ assert_equal("%00%20!%22%23%24%25%26'()*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+ "AZ%5B%5C%5D%5E_%60az%7B%7C%7D~",
+ URI.encode_component("\x00 !\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~"))
+ assert_equal("%E6%9F%8A", URI.encode_component(
+ "\x95\x41".force_encoding(Encoding::Shift_JIS)))
+ assert_equal("%E3%81%82", URI.encode_component(
+ "\x30\x42".force_encoding(Encoding::UTF_16BE)))
+ assert_equal("%E3%81%82", URI.encode_component(
+ "\e$B$\"\e(B".force_encoding(Encoding::ISO_2022_JP)))
+ end
+
+ def test_decode_component
+ assert_equal(" +!\"\#$%&'()*+,-./09:;<=>?@AZ[\\]^_`az{|}~",
+ URI.decode_component(
+ "%20+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
+ "AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E"))
+ assert_equal("\xA1\xA2".force_encoding(Encoding::EUC_JP),
+ URI.decode_component("%A1%A2", "EUC-JP"))
+ assert_equal("\xE3\x81\x82\xE3\x81\x82".force_encoding("UTF-8"),
+ URI.decode_component("\xE3\x81\x82%E3%81%82".force_encoding("UTF-8")))
+
+ assert_raise(ArgumentError){URI.decode_component("%")}
+ assert_raise(ArgumentError){URI.decode_component("%a")}
+ assert_raise(ArgumentError){URI.decode_component("x%a_")}
+ assert_nothing_raised(ArgumentError){URI.decode_component("x"*(1024*1024))}
+ end
+
</span> def test_encode_www_form_component
assert_equal("%00+%21%22%23%24%25%26%27%28%29*%2B%2C-.%2F09%3A%3B%3C%3D%3E%3F%40" \
"AZ%5B%5C%5D%5E_%60az%7B%7C%7D%7E",
</code></pre> Ruby master - Feature #11373 (Open): Add command line option to query valid values for --dumphttps://bugs.ruby-lang.org/issues/113732015-07-18T14:28:52Zmx4492 (Manav Rathi)mx4492@gmail.comRuby master - Feature #11181 (Assigned): 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 #11148 (Open): Add a way to require files, but not raise an exception when ...https://bugs.ruby-lang.org/issues/111482015-05-12T22:48:44Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Hi,</p>
<p>I'm trying to make is so that RubyGems doesn't need to put directories on $LOAD_PATH (which is why I submitted Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Allow rubygems' `require` to handle `autoload` calls (Closed)" href="https://bugs.ruby-lang.org/issues/11140">#11140</a>). I would like the <code>require</code> implemented in RubyGems to look up the file from a cache generated when the gem is installed, then pass a full file path to <code>require</code>.</p>
<p>The problem is that the user may have manipulated the load path somehow, and RubyGems needs to detect if the file is in the load path. Today, the algorithm inside RubyGems looks something like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">require</span> <span class="n">file</span>
<span class="k">if</span> <span class="n">file_is_from_a_default_gem?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="c1"># this is so you can install new versions of default gems</span>
<span class="n">add_default_gem_to_loadpath</span>
<span class="k">end</span>
<span class="n">real_require</span> <span class="n">file</span>
<span class="k">rescue</span> <span class="no">LoadError</span>
<span class="n">gem</span> <span class="o">=</span> <span class="n">find_gem_that_contains_file</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
<span class="n">add_gem_to_loadpath</span> <span class="n">gem</span>
<span class="n">real_require</span> <span class="n">file</span>
<span class="k">end</span>
</code></pre>
<p>Instead of adding the directory to the load path, I would like to look up the full file path from a cache that is generated when the gem is installed. If we had a cache, that means the new implementation would look like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">require</span> <span class="n">file</span>
<span class="k">if</span> <span class="n">file_is_from_a_default_gem?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="c1"># this is so you can install new versions of default gems</span>
<span class="n">add_default_gem_to_loadpath</span>
<span class="k">end</span>
<span class="n">real_require</span> <span class="n">file</span> <span class="c1"># get slower as paths are added to LOAD_PATH</span>
<span class="k">rescue</span> <span class="no">LoadError</span>
<span class="n">gem</span> <span class="o">=</span> <span class="n">find_gem_that_contains_file</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="c1"># use a cache so lookup is O(1)</span>
<span class="n">fully_qualified_path</span> <span class="o">=</span> <span class="n">gem</span><span class="p">.</span><span class="nf">full_path</span> <span class="n">file</span>
<span class="n">real_require</span> <span class="n">fully_qualified_path</span> <span class="c1"># send a fully qualified path, so LOAD_PATH isn't searched</span>
<span class="k">end</span>
</code></pre>
<p>Unfortunately, that means that every call to require in the system would raise an exception. I'd like to add a version of <code>require</code> that we can call that <em>doesn't</em> raise an exception. Then I could write the code like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">require</span> <span class="n">file</span>
<span class="k">if</span> <span class="n">file_is_from_a_default_gem?</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="c1"># this is so you can install new versions of default gems</span>
<span class="n">add_default_gem_to_loadpath</span>
<span class="k">end</span>
<span class="n">found</span> <span class="o">=</span> <span class="n">try_require</span> <span class="n">file</span>
<span class="k">if</span> <span class="kp">nil</span> <span class="o">==</span> <span class="n">found</span>
<span class="n">gem</span> <span class="o">=</span> <span class="n">find_gem_that_contains_file</span><span class="p">(</span><span class="n">file</span><span class="p">)</span> <span class="c1"># use a cache so lookup is O(1)</span>
<span class="n">fully_qualified_path</span> <span class="o">=</span> <span class="n">gem</span><span class="p">.</span><span class="nf">full_path</span> <span class="n">file</span>
<span class="n">real_require</span> <span class="n">fully_qualified_path</span> <span class="c1"># send a fully qualified path, so LOAD_PATH isn't searched</span>
<span class="k">end</span>
<span class="n">found</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>This would keep the load path small, and prevent exceptions from happening during the "normal" case.</p>
<p>I've attached a patch that implements <code>try_require</code>, but I'm not set on the name. Maybe doing <code>require(file, exception: false)</code> would work too.</p> Ruby master - Feature #10489 (Assigned): 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 #9992 (Open): Access Modifiers (Internal Interfaces)https://bugs.ruby-lang.org/issues/99922014-06-28T19:05:49Zdsferreira (Daniel Ferreira)
<p>Hi,</p>
<p>I would like to discuss with you the concept of Internal Interfaces.</p>
<p>Currently ruby offers three access modifiers choices to set methods visibility:</p>
<ul>
<li>public</li>
<li>protected</li>
<li>private</li>
</ul>
<p>Public methods define what we may call the Public Interface.<br>
Private methods are private to the class and its subclasses.<br>
Protected methods are public for the subclasses.</p>
<p>I would like to work with a new access modifier that would allow the creation of Internal methods.</p>
<p>Internal methods would be object methods that could only be called within the namespace.</p>
<p>Ex:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Foo</span><span class="p">;</span> <span class="k">end</span>
<span class="k">class</span> <span class="nc">Foo::Bar</span>
<span class="k">def</span> <span class="nf">baz</span>
<span class="nb">puts</span> <span class="err">‘</span><span class="n">baz</span><span class="err">’</span>
<span class="k">end</span>
<span class="n">internal</span> <span class="ss">:baz</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Foo::Qux</span>
<span class="k">def</span> <span class="nf">baz</span>
<span class="o">::</span><span class="no">Foo</span><span class="o">::</span><span class="no">Bar</span><span class="p">.</span><span class="nf">new</span><span class="p">.</span><span class="nf">baz</span>
<span class="k">end</span>
<span class="kp">public</span> <span class="ss">:baz</span>
<span class="k">end</span>
</code></pre>
<p>What about this use case:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Foo</span><span class="p">;</span> <span class="k">end</span>
<span class="c1">##</span>
<span class="c1"># Template class</span>
<span class="c1">#</span>
<span class="c1"># ==== Example</span>
<span class="c1"># </span>
<span class="c1"># Foo::SubClass.run(:arg1)</span>
<span class="c1"># #=> ...</span>
<span class="k">class</span> <span class="nc">Foo::Base</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
<span class="vi">@arg</span> <span class="o">=</span> <span class="n">arg</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">run</span><span class="p">(</span><span class="n">arg</span><span class="p">)</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="n">arg</span><span class="p">).</span><span class="nf">perform</span>
<span class="k">end</span>
<span class="nb">public_class_method</span> <span class="ss">:run</span>
<span class="c1">##</span>
<span class="c1"># Override abstract method</span>
<span class="k">def</span> <span class="nf">perform</span>
<span class="k">raise</span> <span class="no">NotImplementedError</span>
<span class="k">end</span>
<span class="n">internal</span> <span class="ss">:perform</span>
<span class="k">end</span>
<span class="c1">##</span>
<span class="c1"># Test subclass.</span>
<span class="c1"># </span>
<span class="c1"># ==== Example</span>
<span class="c1">#</span>
<span class="c1"># Foo::Bar.run("Hello!")</span>
<span class="c1"># # => My argument is Hello!</span>
<span class="k">class</span> <span class="nc">Foo::Bar</span> <span class="o"><</span> <span class="no">Foo</span><span class="o">::</span><span class="no">Base</span>
<span class="k">def</span> <span class="nf">perform</span>
<span class="nb">puts</span> <span class="s2">"My argument is: "</span> <span class="o">+</span> <span class="vi">@arg</span>
<span class="k">end</span>
<span class="n">internal</span> <span class="ss">:perform</span>
<span class="k">end</span>
</code></pre>
<p>Is this something that we can think about in a future implementation of ruby?<br>
An extra feature that would not break backward compatibility.</p>
<p>Cheers,<br>
Daniel</p> Ruby master - Feature #9556 (Open): Add HTTP#get block functionality to HTTP.gethttps://bugs.ruby-lang.org/issues/95562014-02-23T05:53:38Zsrawlins (Sam Rawlins)sam.rawlins@gmail.com
<p>This is kind of an alternative to <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: make Net::HTTP.get_print not only to $stdout but to an IO as a parameter (Open)" href="https://bugs.ruby-lang.org/issues/9527">#9527</a>.</p>
<p>HTTP#get can be passed a block. The shortcut method, HTTP.get, however, cannot. This patch adds such functionality.</p>
<p>This allows someone to be able to write the response of a GET, in fragments, without dealing directly with Net::HTTPResponse, like the request in <a class="issue tracker-2 status-1 priority-4 priority-default" title="Feature: make Net::HTTP.get_print not only to $stdout but to an IO as a parameter (Open)" href="https://bugs.ruby-lang.org/issues/9527">#9527</a>:</p>
<pre><code>File.open('result.zip', 'wb') {|f|
Net::HTTP.get('www.example.com', '/file.zip') do |chunk|
f.write chunk
end
}
</code></pre>
<p>This patch includes that example as documentation, and a test. It is attached, and available at: <a href="https://github.com/srawlins/ruby/compare/add-block-to-http-get" class="external">https://github.com/srawlins/ruby/compare/add-block-to-http-get</a></p> Ruby master - Feature #9347 (Assigned): Accept non callable argument to detecthttps://bugs.ruby-lang.org/issues/93472014-01-03T07:37:33Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Currently, the only argument that <code>Enumerable#detect</code> accepts is a callable object.</p>
<p>Shouldn't we accept non callable objects too?</p>
<pre><code>[42].detect(:not_found){} # => NoMethodError: undefined method `call' for :not_found:Symbol
# would return :not_found instead.
</code></pre>
<p>I'd suggest that if the given argument does not <code>respond_to? :call</code>, then it would be returned as is instead of raising an error as currently.<br>
Wouldn't this be more flexible and possibly more performant?</p>
<p>Inspired by <a href="http://stackoverflow.com/questions/20883414/why-does-enumerabledetect-need-a-proc-lambda" class="external">http://stackoverflow.com/questions/20883414/why-does-enumerabledetect-need-a-proc-lambda</a></p> Ruby master - Feature #9185 (Open): Add alias_class_method or class_alias functionalityhttps://bugs.ruby-lang.org/issues/91852013-12-01T03:39:32Zshevegen (Robert A. Heiler)shevegen@gmail.com
<p>Hi core team,</p>
<p>First drink a Calpis (カルピス Karupisu) before reading on :-)</p>
<p>Now, my proposal is to add a slight new feature that is mostly one of convenience.</p>
<p>We have two ways to use aliases:</p>
<p>(1) alias<br>
(2) alias_method</p>
<p>But are similar but not 100% the same.</p>
<p>Now this works all fine and nice.</p>
<p>But how to define a class method? Well, simple:</p>
<p>class Foo; def self.hi; puts 'hi'; end; end; Foo.hi</p>
<p>But how can we make an alias to this class method?</p>
<p>Well, this is ugly - here is one way:</p>
<p>class Foo; class << self; def ho; hi; end;end;end</p>
<p>Is this readable to you?</p>
<p>Using alias would be more readable.</p>
<p>Ok, we can simplify it by using alias:</p>
<p>class Foo; class << self; alias ho hi; end;end</p>
<p>But I don't like the class << self there, just to make<br>
a single class alias.</p>
<p>I thus propose a new method called:</p>
<p>class_alias</p>
<p>The above could then be rewritte like so perhaps:<br>
class Foo; class_alias :ho, :hi; end # I guess this would be more akin to alias_method</p>
<p>If the name is bad, it could be:</p>
<p>alias_class_method</p>
<p>Perhaps. Anyway, the name is not so important, I am sure a good name can be found,<br>
but I wonder if this would be a good feature to add or not.</p>
<p>Thanks for reading!</p> Ruby master - Feature #8960 (Assigned): Add Exception#backtrace_locationshttps://bugs.ruby-lang.org/issues/89602013-09-27T20:11:45Zheadius (Charles Nutter)headius@headius.com
<p>All parties agreed this would be useful to add in <a href="https://bugs.ruby-lang.org/issues/7895" class="external">https://bugs.ruby-lang.org/issues/7895</a> and ko1 suggested I file a feature against ruby-trunk. So here it is.</p>
<p>I might be able to come up with a patch, but I'm not sure when. Help wanted.</p>
<p>Can we agree this will go into 2.1?</p> Ruby master - Feature #8626 (Open): Add a Set coercion method to the standard lib: Set(possible_set)https://bugs.ruby-lang.org/issues/86262013-07-12T01:26:27Zsaturnflyer (Jim Gay)
<p>=begin<br>
I'd like to be able to take an object that may already be a Set (or not) and ensure that it is one</p>
<p>For example:</p>
<pre><code>set1 = Set.new
set2 = Set(set1)
set3 = Set(nil)
assert set1.equal?(set2)
assert_instance_of(Set, set3)
</code></pre>
<p>This is different from the behavior of Set.new in that it will return the same set rather than creating a new one</p>
<pre><code>set1 = Set.new
set2 = Set.new(set1) # <--- completely new object in memory
set2 = Set(set1) # <--- same object from memory
</code></pre>
<p>My thoughts about the implementation are simple:</p>
<pre><code>def Set(possible_set)
possible_set.is_a?(Set) ? possible_set : Set.new(possible_set)
end
</code></pre>
<p>I'm not sure if there are edge cases to unexpected behavior that I haven't thought of and I'm wondering if it ought to have a Set.try_convert as well<br>
=end</p> Ruby master - Feature #8042 (Assigned): Add Addrinfo#socket to create a socket that is not connec...https://bugs.ruby-lang.org/issues/80422013-03-08T08:35:01Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>This adds a socket method to Addrinfo to get a socket that has not been bound or connected to any address for connectionless operation.</p> Ruby master - Feature #7876 (Assigned): 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 #7704 (Assigned): 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 #7362 (Assigned): Adding Pathname#start_with?https://bugs.ruby-lang.org/issues/73622012-11-15T22:38:40Zaef (Alexander E. Fischer)aef@raxys.net
<p>If a Pathname starts with another Pathname, that means that the former Pathname lies below the latter Pathname, as long as both Pathnames are interpreted from the same location or both are given as absolute.</p>
<p>Therefore I would like to see a method #start_with? just like the one on String but for Pathnames.</p>
<p>If you like the idea, just tell me. I will provide a patch then.</p> Ruby master - Feature #6973 (Assigned): Add an #integral? method to Numeric to test for whole-num...https://bugs.ruby-lang.org/issues/69732012-09-04T06:03:43Zregularfry (Alex Young)alex@blackkettle.org
<p>Numeric#integer? checks whether an instance is an Integer. It is often useful to check whether the value of a non-Integer variable is actually a whole number, and the #integer? method doesn't help here.</p>
<p>This patch adds Numeric#integral?, which performs this check.</p> Ruby master - Feature #6682 (Assigned): Add a method to return an instance attached by a singleto...https://bugs.ruby-lang.org/issues/66822012-07-01T19:22:05Zryoqun (Ryo Onodera)ryoqun@gmail.com
<p>=begin<br>
Currently, there is no easy way to get the attached instance from a singleton class. For MRI, we have to resort to writing an C extension. So it'll be useful to add an instance method to Class to return the attached instance if the given class object is a singleton class.</p>
<p>I'll show what I want in the code-wise with the following code snippet:</p>
<p>text = "I love Ruby."<br>
klass = text.singleton_class</p>
<a name="gt-ltClassString0x000000027383e8gt"></a>
<h1 >=> #<Class:#<a href="String:0x000000027383e8" class="external">String:0x000000027383e8</a>><a href="#gt-ltClassString0x000000027383e8gt" class="wiki-anchor">¶</a></h1>
<p>klass.singleton_instance # <= This is the new method.</p>
<a name="gt-I-love-Ruby"></a>
<h1 >=> "I love Ruby."<a href="#gt-I-love-Ruby" class="wiki-anchor">¶</a></h1>
<p>String.singleton_instance # <= This should return nil because String isn't a singleton class and there is no singleton instance, rather there will be many instances.</p>
<a name="gt-nil"></a>
<h1 >=> nil<a href="#gt-nil" class="wiki-anchor">¶</a></h1>
<p>As for use cases, in my case, I wanted to create a module to add class methods. And it has some state, so must be initialized properly. And it can equally be used by Class#extend and Class#include like this:</p>
<p>module Countable<br>
attr_reader(:count)</p>
<pre><code>class << self
def extended(extended_class)
p("extending #{extended_class}")
super
initialize_state(extended_class)
end
def included(included_class)
p("including #{included_class}")
super
if included_class.singleton_instance # <= Currently, I can't do this.
initialize_state(included_class.singleton_instance)
end
end
private
def initialize_state(object)
p("initializing state of #{object}")
object.instance_variable_set(:@count, 0)
end
end
</code></pre>
<p>end</p>
<p>class Person<br>
extend(Countable)<br>
end</p>
<p>class Book<br>
class << self<br>
include(Countable)<br>
end<br>
end</p>
<p>p(Person.count)<br>
p(Book.count)</p>
<a name="gt-extending-Person"></a>
<h1 >=> "extending Person"<a href="#gt-extending-Person" class="wiki-anchor">¶</a></h1>
<a name="gt-initializing-state-of-Person"></a>
<h1 >=> "initializing state of Person"<a href="#gt-initializing-state-of-Person" class="wiki-anchor">¶</a></h1>
<a name="gt-including-ClassBook"></a>
<h1 >=> "including #<a href="Class:Book" class="external">Class:Book</a>"<a href="#gt-including-ClassBook" class="wiki-anchor">¶</a></h1>
<a name="gt-initializing-state-of-Book"></a>
<h1 >=> "initializing state of Book"<a href="#gt-initializing-state-of-Book" class="wiki-anchor">¶</a></h1>
<a name="gt-0"></a>
<h1 >=> 0<a href="#gt-0" class="wiki-anchor">¶</a></h1>
<a name="gt-0-2"></a>
<h1 >=> 0<a href="#gt-0-2" class="wiki-anchor">¶</a></h1>
<p>Others wanted this functionality as shown by ((<this stackoverflow page|URL:<a href="http://stackoverflow.com/questions/7053455/given-a-ruby-metaclass-how-do-i-get-the-instance-to-which-it-is-attached%3E" class="external">http://stackoverflow.com/questions/7053455/given-a-ruby-metaclass-how-do-i-get-the-instance-to-which-it-is-attached></a>)). Also, I found several actual C-extensions for this kind of functionality on the wild browsing ((<a search result|URL:<a href="https://github.com/search?q=rb_iv_get+__attached__&repo=&langOverride=&start_value=1&type=Code&language=C%3E" class="external">https://github.com/search?q=rb_iv_get+__attached__&repo=&langOverride=&start_value=1&type=Code&language=C></a>)) on github.</p>
<ul>
<li>((<eigen|URL:<a href="https://github.com/elliottcable/refinery/blob/853dcc2254557200d1d6be4cb9c105e8fa9d01a9/ext/eigen/eigen.c#L12%3E" class="external">https://github.com/elliottcable/refinery/blob/853dcc2254557200d1d6be4cb9c105e8fa9d01a9/ext/eigen/eigen.c#L12></a>))</li>
<li>((<mult|URL:<a href="https://github.com/banister/mult/blob/6a1d0bdd383e7e231c5b7c2c718204dfb6ba28ca/ext/mult/mult.c#L43%3E" class="external">https://github.com/banister/mult/blob/6a1d0bdd383e7e231c5b7c2c718204dfb6ba28ca/ext/mult/mult.c#L43></a>))</li>
</ul>
<p>Thanks for creating a great language. Especially I love its meta-programming capability. I'd wish this feature to lead to better meta-programming capability of Ruby.<br>
=end</p> Ruby master - Feature #6309 (Assigned): Add a reference queue for weak referenceshttps://bugs.ruby-lang.org/issues/63092012-04-17T17:10:15Zheadius (Charles Nutter)headius@headius.com
<p>Most interesting uses of WeakRef are much harder to do efficiently without a reference queue.</p>
<p>A reference queue, as implemented by the JVM, is basically a queue into which weak references are placed some time after the object they refer to has been collected. The queue can be polled cheaply to look for collected references.</p>
<p>A simple example of usage can be seen in the weakling gem, with an efficient implementation of an ID hash: <a href="https://github.com/headius/weakling/blob/master/lib/weakling/collections.rb" class="external">https://github.com/headius/weakling/blob/master/lib/weakling/collections.rb</a></p>
<p>Notice the _cleanup method is called for every operation, to keep the hash clear of dead references. Failure to have a _cleanup method would mean the hash grows without bounds.</p>
<p>_cleanup cannot be implemented efficiently on MRI at present because there's no reference queue implementation. On MRI, _cleanup would have to perform a linear scan of all stored values periodically to search for dead references. For a heavily used hash with many live values, this becomes a very expensive operation.</p>
<p>It's probably possible to implement reference queues efficiently atop the new ObjectSpace::WeakMap internals, since it already keeps track of weak references and can run code when a weak reference no longer refers to a live object.</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 #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>