Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112024-01-08T20:56:25ZRuby Issue Tracking System
Redmine 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 - Bug #19761 (Open): AddressSanitizer fails with Thread and Processhttps://bugs.ruby-lang.org/issues/197612023-07-08T07:26:56Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<p>With AddressSanitizer on macOS, this code crashes.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">system</span><span class="p">(</span><span class="s1">''</span><span class="p">)</span>
<span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="p">{}</span>
<span class="mi">300_000</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="no">String</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">capacity: </span><span class="mi">1000</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<pre><code>==62870==ERROR: AddressSanitizer failed to deallocate 0x8000 (32768) bytes at address 0x62d00000a400
AddressSanitizer: CHECK failed: sanitizer_posix.cpp:61 "(("unable to unmap" && 0)) != (0)" (0x0, 0x0) (tid=857549)
<empty stack>
Assertion Failed: ../debug/vm_core.h:1853:rb_current_execution_context:!expect_ec || ec != NULL
ruby 3.3.0dev (2023-07-08T02:54:37Z tmp 0083edc3a0) [x86_64-darwin22]
-- Crash Report log information --------------------------------------------
See Crash Report log file in one of the following locations:
* ~/Library/Logs/DiagnosticReports
* /Library/Logs/DiagnosticReports
for more details.
Don't forget to include the above Crash Report log file in bug reports.
-- C level backtrace information -------------------------------------------
</code></pre> Ruby master - Feature #19694 (Open): Add Regexp#timeout= setterhttps://bugs.ruby-lang.org/issues/196942023-05-25T18:55:58Zaharpole (Aaron Harpole)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>In addition to allowing for a Regexp timeout to be set on individual instances by setting a <code>timeout</code> argument in <code>Regexp.new</code>, I'm proposing that we also allow setting the timeout on Regexp objects with a <code>#timeout=</code> setter.</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>To be able to roll out a global Regexp timeout for a large application, there are inevitably some individual regexes for which a different timeout is appropriate. While the <code>timeout</code> keyword argument was added to <code>Regexp.new</code>, this isn't always a viable option.</p>
<p>In the case of regex literal syntax (<code>/ab*/</code> or <code>%r{ab*}</code>, for instance), it's not possible to set a timeout at all right now without converting to <code>Regexp.new</code>, which may be awkward depending on the contents of the regex.</p>
<p>It also is desirable from time to time to be able to set a timeout for a regex object after it's been initialized.</p>
<p>Finally, because we offer a <code>Regexp#timeout</code> getter, for consistency it would be nice to also offer a setter.</p>
<p>The introduction of a <code>Regexp#timeout=</code> setter was mentioned as a possible way to set individual timeouts in <a href="https://bugs.ruby-lang.org/issues/19104#Specification" class="external">https://bugs.ruby-lang.org/issues/19104#Specification</a>.</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>I propose that we add the method <code>Regexp#timeout=</code>. It works the same way the <code>timeout</code> argument works in <code>Regexp.new</code>, taking either a float or nil.</p>
<p>This makes it relatively easy to add timeouts to specific regex literals (regex literals are frozen by default so you do have to <code>dup</code> them first):</p>
<pre><code>emoji_filter_pattern = %r{
(?<!#{Regexp.quote(ZERO_WIDTH_JOINER)})
#{EmojiFilter.unicodes_pattern}
(?!#{Regexp.union(EmojiFilter::MODIFIER_CHAR_MAP.keys.map { |k| Regexp.quote k })})
}x.dup
emoji_filter_pattern.timeout = 1.0
emoji_filter_pattern.freeze
</code></pre>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p>This setter has been implemented in <a href="https://github.com/ruby/ruby/pull/7847" class="external">https://github.com/ruby/ruby/pull/7847</a>.</p>
<a name="Evaluation"></a>
<h1 >Evaluation<a href="#Evaluation" class="wiki-anchor">¶</a></h1>
<p>It's just a setter, so pretty straightforward in terms of implementation and use.</p>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<p>It's worth considering other options for overriding <code>Regexp.timeout</code>. I'd love to see something like the following for overriding regexp timeouts as well:</p>
<pre><code>Regexp.timeout = 1.0
Regexp.with_timeout(5.0) do
evaluate_slower_regexes
end
</code></pre>
<p>It's possible to implement something like <code>Regexp.with_timeout</code> but it's not thread-safe by default since it would involve overwriting <code>Regexp.timeout</code>.</p>
<a name="Summary"></a>
<h1 >Summary<a href="#Summary" class="wiki-anchor">¶</a></h1>
<p>Regexp instances have a getter for timeout, and adding a corresponding setter adds consistency and will make it easier for developers to adopt adding a global <code>Regexp.timeout</code> by making it simpler to adjust timeouts on a regex by regex basis.</p>
<p>It's a minor change but the added consistency and flexibility help us optimize for developer happiness.</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 #19567 (Open): Add Oxford Comma Support for better readabilityhttps://bugs.ruby-lang.org/issues/195672023-04-01T05:27:35Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Ruby has regular commas:</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="n">c</span><span class="p">]</span>
</code></pre>
<p>Ruby has trailing commas:</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="n">c</span><span class="p">,</span>
<span class="p">]</span>
</code></pre>
<p>But I think both of these are hard to read compared to the Oxford comma.<br>
We should introduce the Oxford comma so that code is easier to read:</p>
<p>For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">foo</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="ow">and</span> <span class="n">c</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="ow">and</span> <span class="n">c</span><span class="p">]</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="n">foo</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="ow">and</span> <span class="mi">3</span><span class="p">)</span>
</code></pre>
<p>As an added bonus, this feature also makes specifying musical beats<br>
quite natural, for example:</p>
<pre><code>[1, and 2, and 3, and 4]
</code></pre>
<p>Just to make sure that everyone is pleased, you are allowed to mix the<br>
Oxford comma with trailing commas like this:</p>
<pre><code>[
1,
and 2,
and 3,
and 4,
]
</code></pre> 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 - 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 #18675 (Open): Add new exception class for resolv timeoutshttps://bugs.ruby-lang.org/issues/186752022-04-01T18:33:24Zgeffatpier64 (Geff Hanoain)
<p>I have 2.7.4 but I also checked 3.0, same code in resolv.rb.</p>
<p>to reproduce:</p>
<pre><code>irb(main):001:0> require 'resolv'
=> true
irb(main):002:0> Resolv::DNS.new(nameserver: ['127.0.0.5']).getaddress("google.com")
Traceback (most recent call last):
5: from /usr/bin/irb:23:in `<main>'
4: from /usr/bin/irb:23:in `load'
3: from /usr/share/gems/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
2: from (irb):2
1: from /usr/share/ruby/resolv.rb:379:in `getaddress'
Resolv::ResolvError (DNS result has no information for google.com)
irb(main):003:0>
</code></pre>
<p>Ideal Expectation:</p>
<pre><code>#<Resolv::ResolvTimeout: Resolv::ResolvTimeout>
</code></pre>
<p>suggested fix:</p>
<pre><code>class Resolv
class DNS
class Config
def resolv(name)
candidates = generate_candidates(name)
timeouts = @timeouts || generate_timeouts
begin
candidates.each {|candidate|
begin
timeouts.each {|tout|
@nameserver_port.each {|nameserver, port|
begin
yield candidate, tout, nameserver, port
rescue ResolvTimeout
end
}
}
#raise ResolvError.new("DNS resolv timeout: #{name}")
raise ResolvTimeout
rescue NXDomain
end
}
#rescue ResolvError
end
end
end
end
end
</code></pre>
<p>I have commented out the code that seemed to arbitrarily swallow any raised exception.</p>
<p><a href="https://github.com/ruby/ruby/blob/ruby_2_7/lib/resolv.rb" class="external">https://github.com/ruby/ruby/blob/ruby_2_7/lib/resolv.rb</a> - line 1125</p>
<pre><code> rescue ResolvError
</code></pre>
<p>I would prefer raising ResolvTimeout to ResolvError.new("DNS resolv timeout: #{name}")</p>
<p>But as long is it does something that isn't:</p>
<pre><code>DNS result has no information for google.com
</code></pre>
<p>I'd be okay with it. I'm happy to help with this via a pull request in github, a diff patch or what ever is needed. I just didn't want to spend too much time "fixing" it the "wrong" way. I'm not intimately familiar with the code in resolv.rb so I'm not 100% sure my "fix" wouldn't break other stuff. I did some minor testing of my minor change.</p>
<p>Separately - This also highlights that a timeout condition isn't in or doesn't work in unit tests.</p>
<p>Thanks so much,</p> 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 #18418 (Open): Add Net::HTTP#security_level=https://bugs.ruby-lang.org/issues/184182021-12-19T11:58:52Zhoshinotsuyoshi (tsuyoshi hoshino)
<a name="Use-Case"></a>
<h3 >Use Case:<a href="#Use-Case" class="wiki-anchor">¶</a></h3>
<p>I want to connect to an HTTP(S) server (using <code>Net::HTTP</code>) that cannot connect with security level<sup><a href="#fn-1" id="fnref-1">1</a></sup> 2 and needs to specify security level 1.<br>
My server is a newer debian (docker image <code>ruby:3.0.3</code>, based on debian bullseye) and I need to change the configuration in <code>/etc/ssl/openssl.cnf</code> to do the above.<br>
And I really don't want to do that, because it affects other SSL communication between my server and other servers.</p>
<hr>
<p>So it would be nice if there is a <code>Net::HTTP#security_level=</code> that can change the <code>OpenSSL::SSL::SSLContext</code> instance, just like we already have <code>Net::HTTP#max_version=</code>.</p>
<p>Note that similar information has been posted<sup><a href="#fn-2" id="fnref-2">2</a></sup> to the mailing list in the past.</p>
<ol>
<li id="fn-1">
<p><a href="https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html" class="external">https://www.openssl.org/docs/man1.1.1/man3/SSL_CTX_set_security_level.html</a> <a href="#fnref-1" aria-label="Back to reference 1">↩</a></p>
</li>
<li id="fn-2">
<p><a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/50825" class="external">http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/50825</a> <a href="#fnref-2" aria-label="Back to reference 2">↩</a></p>
</li>
</ol>
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 - 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 - Bug #18131 (Open): addr2line.c: Some inlined functions mistakenly shownhttps://bugs.ruby-lang.org/issues/181312021-08-24T19:59:25Zxtkoba (Tee KOBAYASHI)
<p>What is observed in ppc64le CI (pathnames edited for readability):</p>
<pre><code>-- C level backtrace information -------------------------------------------
/home/xxx/ruby/ruby(rb_vm_bugreport+0x198) [0x6430d199028] vm_dump.c:759
/home/xxx/ruby/ruby(ibf_load_small_value+0x78) [0x6430cf011c8] error.c:815
/home/xxx/ruby/ruby(ibf_load_iseq_each) compile.c:11650
/home/xxx/ruby/ruby(vm_respond_to) compile.c:12594
/home/xxx/ruby/ruby(rb_ec_obj_respond_to) vm_method.c:2576
/home/xxx/ruby/ruby(rb_obj_respond_to) vm_method.c:2569
/home/xxx/ruby/ruby(rb_bug_for_fatal_signal) vm_method.c:2584
/home/xxx/ruby/ruby(sigsegv+0x64) [0x6430d0bb954] signal.c:961
linux-vdso64.so.1(__kernel_sigtramp_rt64+0x0) [0x795f1d6304c8]
/home/xxx/ruby/ruby(rb_ary_push+0x2c) [0x6430d1b31cc] array.c:1313
(...)
</code></pre>
<p>Here, 6 functions are shown for address <code>0x6430cf011c8</code>, of which only <code>rb_bug_for_fatal_signal</code> is valid.</p>
<p>I have not yet come up with how to fix this, but I suspect this is partially due to <code>ranges_include</code> in <code>addr2line.c</code> not handling <code>DW_AT_entry_pc</code> at all.</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-1 priority-4 priority-default" title="Feature: Introduce a new "shortcut assigning" syntax to convenient setup instance variables (Open)" 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-1 priority-4 priority-default" title="Feature: Introduce a new "shortcut assigning" syntax to convenient setup instance variables (Open)" 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 #17753 (Open): Add Module#namespacehttps://bugs.ruby-lang.org/issues/177532021-03-26T19:19:42Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Given code like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">A</span>
<span class="k">module</span> <span class="nn">B</span>
<span class="k">class</span> <span class="nc">C</span><span class="p">;</span> <span class="k">end</span>
<span class="k">class</span> <span class="nc">D</span><span class="p">;</span> <span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>We can get from <code>C</code> to <code>B</code> like <code>C.outer_scope</code>, or to <code>A</code> like<br>
<code>C.outer_scope.outer_scope</code>.</p>
<p>I want to use this in cases where I don't know the outer scope, but I<br>
want to find constants that are "siblings" of a constant. For example,<br>
I can do <code>A::B::C.outer_scope.constants</code> to find the list of "sibling"<br>
constants to <code>C</code>. I want to use this feature when walking objects and<br>
introspecting. For example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">ObjectSpace</span><span class="p">.</span><span class="nf">each_object</span><span class="p">(</span><span class="no">Class</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">k</span><span class="o">|</span>
<span class="nb">p</span> <span class="ss">siblings: </span><span class="n">k</span><span class="p">.</span><span class="nf">outer_scope</span><span class="p">.</span><span class="nf">constants</span>
<span class="k">end</span>
</code></pre>
<p>I've attached a patch that implements this feature, and there is a pull request on GitHub <a href="https://github.com/ruby/ruby/pull/4326" class="external">here</a>.</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 #17406 (Open): Add `NoMatchingPatternError#depth`https://bugs.ruby-lang.org/issues/174062020-12-18T21:45:35Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<p>Could we have <code>NoMatchingPatternError#depth</code>, returning the number of <code>case...in...end</code> an exception has traversed?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">show_depth</span>
<span class="k">yield</span>
<span class="k">rescue</span> <span class="no">NoMatchingPatternError</span> <span class="o">=></span> <span class="n">e</span>
<span class="nb">puts</span> <span class="s2">"Depth: </span><span class="si">#{</span><span class="n">e</span><span class="p">.</span><span class="nf">depth</span><span class="si">}</span><span class="s2">"</span>
<span class="k">raise</span>
<span class="k">end</span>
<span class="n">show_depth</span> <span class="k">do</span>
<span class="k">case</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="k">in</span> <span class="p">[</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">]</span> <span class="k">then</span>
<span class="n">show_depth</span> <span class="k">do</span>
<span class="n">x</span> <span class="o">=></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="c1"># => raises NoMatchingPatternError</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="c1"># Prints "Depth: 0" then "Depth: 1"</span>
</code></pre>
<p>This could help bring pattern match closer to a language construct people can play with.</p>
<p>Example usecase: implement <code>Ractor#receive_if</code> as in <a href="https://bugs.ruby-lang.org/issues/17378#note-6" class="external">https://bugs.ruby-lang.org/issues/17378#note-6</a></p> Ruby master - Feature #17375 (Open): Add scheduler callbacks for transferring fibershttps://bugs.ruby-lang.org/issues/173752020-12-07T23:31:22Znevans (Nicholas Evans)
<p>When working on <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Adds Fiber#cancel, which forces a Fiber to break/return (Closed)" href="https://bugs.ruby-lang.org/issues/17325">#17325</a> (<code>Fiber#cancel</code>) and <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Let Fiber#raise work with transferring fibers (Closed)" href="https://bugs.ruby-lang.org/issues/17331">#17331</a> (<code>Fiber#raise</code> on transferring fibers), two very reasonable questions keep coming up:</p>
<ul>
<li>"how and when should control pass back to the current fiber?" and</li>
<li>"is it expected that terminating fibers will return to the root fiber chain?"</li>
</ul>
<p>Rather than deal with that complexity, I've passed the buck: that's out of scope for those tickets. The end user should just call their scheduler library and let it coordinate, right?</p>
<p>But with a couple of optional hooks on the scheduler, I think we can answer both of those questions. I'm not sure that these are the ideal API, but what do you think about <em>something</em> similar to the following?</p>
<a name="how-and-when-should-control-pass-back-to-the-current-fiber"></a>
<h3 >"how and when should control pass back to the current fiber?"<a href="#how-and-when-should-control-pass-back-to-the-current-fiber" class="wiki-anchor">¶</a></h3>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Called before transferring into another fiber.</span>
<span class="c1"># @param target [Fiber] the fiber that will be transferred into</span>
<span class="c1"># @param reason [:transfer, :raise, :cancel] How the transfer was initiated </span>
<span class="c1"># @param args the arguments sent to transfer, raise, or cancel.</span>
<span class="c1">#</span>
<span class="c1"># @raise [FiberTransferInterrupted] to prevent the transfer without raising an</span>
<span class="c1"># exception in the calling fiber.</span>
<span class="c1"># @raise [Exception] prevents the transfer and raises in the calling fiber</span>
<span class="c1">#</span>
<span class="c1"># This can be used to ensure the current fiber is appropriately scheduled for</span>
<span class="c1"># return, and it can also prevent the transfer or schedule the transfer to</span>
<span class="c1"># happen asynchronously.</span>
<span class="c1">#</span>
<span class="c1"># In addition to raising exceptions, any call to a fiber switching method (e.g.</span>
<span class="c1"># resume, yield, or transfer) will prevent the transfer. When a transfer is</span>
<span class="c1"># prevented, any associated cancellation or exception will not happen.</span>
<span class="c1">#</span>
<span class="c1"># This will only be called for transfers, not for resume, yield, or termination.</span>
<span class="k">def</span> <span class="nf">transferring</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="n">reason</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="c1"># one possible implementation:</span>
<span class="k">return</span> <span class="k">if</span> <span class="no">Fiber</span><span class="p">.</span><span class="nf">current</span> <span class="o">==</span> <span class="vi">@scheduler</span> <span class="c1"># always allow transfer from scheduler</span>
<span class="k">if</span> <span class="n">target</span> <span class="o">==</span> <span class="vi">@scheduler</span>
<span class="c1"># guard transfer to the scheduler</span>
<span class="k">raise</span> <span class="no">FiberError</span><span class="p">,</span> <span class="s2">"invalid transfer to scheduler"</span> <span class="k">if</span> <span class="n">invalid?</span><span class="p">(</span><span class="n">reason</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
<span class="k">else</span>
<span class="c1"># schedule all transfers instead of running immediately</span>
<span class="vi">@next_tick</span> <span class="o"><<</span> <span class="p">[</span><span class="n">target</span><span class="p">,</span> <span class="n">reason</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">]</span>
<span class="vi">@next_tick</span> <span class="o"><<</span> <span class="p">[</span><span class="no">Fiber</span><span class="p">.</span><span class="nf">current</span><span class="p">,</span> <span class="ss">:transfer</span><span class="p">]</span> <span class="k">unless</span> <span class="n">blocking?</span>
<span class="vi">@scheduler</span><span class="p">.</span><span class="nf">transfer</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>This would be useful for more than just <code>Fiber#raise</code> and <code>Fiber#cancel</code>. It could allows any non-scheduler code to safely call <code>Fiber#transfer</code> (or to indirectly transfer via <code>#raise</code> or <code>#cancel</code>) without confusing or breaking the scheduler. Or the scheduler could <strong>disallow</strong> any transfers but its own. Or it could intercept certain internal framework exceptions. It allows the scheduler some control over transfer and over raise/cancel with transferring fibers.</p>
<a name="exceptions-raised-from-terminating-transferred-fibers-will-return-to-the-root-fiber-chain"></a>
<h3 >"exceptions raised from terminating transferred fibers will return to the root fiber chain"<a href="#exceptions-raised-from-terminating-transferred-fibers-will-return-to-the-root-fiber-chain" class="wiki-anchor">¶</a></h3>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Select the return fiber for a transferring fiber when it terminates.</span>
<span class="c1"># @param terminating [Fiber] The terminating fiber</span>
<span class="c1"># @param retval [Object] return value of the terminating fiber</span>
<span class="c1"># @param error [Exception, nil] raised by terminating fiber</span>
<span class="c1"># @return [Fiber, nil] fiber to transfer into. `nil` uses default behavior</span>
<span class="c1">#</span>
<span class="c1"># If the selected return fiber can't be transferred to (because it is yielding</span>
<span class="c1"># or resuming or dead), FiberError will be raised on root fiber chain.</span>
<span class="c1">#</span>
<span class="c1"># This will be run in the terminating fiber after its block has completed.</span>
<span class="c1"># If this raises an exception, that will be raised on the root fiber chain.</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">select_return_fiber</span><span class="p">(</span><span class="n">terminating</span><span class="p">,</span> <span class="n">retval</span><span class="p">,</span> <span class="n">error</span><span class="p">)</span>
<span class="n">supervisor</span> <span class="o">=</span> <span class="vi">@supervised</span><span class="p">[</span><span class="n">terminating</span><span class="p">]</span>
<span class="k">if</span> <span class="n">supervisor</span><span class="o">&</span><span class="p">.</span><span class="nf">alive?</span>
<span class="n">supervisor</span>
<span class="k">elsif</span> <span class="vi">@scheduled</span><span class="p">.</span><span class="nf">include?</span><span class="p">(</span><span class="n">terminating</span><span class="p">)</span>
<span class="vi">@scheduler</span>
<span class="k">elsif</span> <span class="o">!</span><span class="n">error</span>
<span class="k">raise</span> <span class="no">FiberError</span><span class="p">,</span> <span class="s2">"unsupervised transfer fiber terminated"</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>In addition to answering the question raised by <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Adds Fiber#cancel, which forces a Fiber to break/return (Closed)" href="https://bugs.ruby-lang.org/issues/17325">#17325</a> and <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Let Fiber#raise work with transferring fibers (Closed)" href="https://bugs.ruby-lang.org/issues/17331">#17331</a>, I think this also simplifies some other useful patterns, e.g. supervisors.</p>
<p>It would also let me easily fix one of the things that ruby 3.0 breaks in my current code: I liked to "init" my transfer fibers by first resuming into them from their supervisor and then immediately transferring back out. That sets the return_fiber for when it terminates. A workaround is to use an ensured <code>supervisor.transfer</code> on the last line of the fiber and then abandon the almost dead fiber. But that might lead to a bug later if some other code held onto a reference to that fiber, saw it was still alive, and transferred into it (unlikely, but plausible). And it's still brittle: if any errant code calls <code>Fiber.yield</code>, the return_fiber will be lost and can never be recovered. Letting the scheduler manage this would provide the lost ruby 2 functionality and more.</p>
<p>What do you think?</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 #17208 (Open): Add `Set#compact` and `Set#compact!` methodshttps://bugs.ruby-lang.org/issues/172082020-10-01T19:32:01Zkoic (Koichi ITO)koic.ito@gmail.com
<p>This is a proposal to add <code>compact</code> and <code>compact!</code> methods already owned by <code>Array</code> and <code>Hash</code> to <code>Set</code>.</p>
<ul>
<li>
<code>Array#compact</code> and <code>Array#compact!</code> has been around for a long time.</li>
<li>
<code>Hash#compact</code> has <code>Hash#compact!</code> been added since Ruby 2.4 ... <a href="https://bugs.ruby-lang.org/issues/11818" class="external">https://bugs.ruby-lang.org/issues/11818</a>
</li>
<li>There is <code>Set</code> in collection libraries other than <code>Array</code> and <code>Hash</code>. But <code>Set</code> doesn't have <code>compact</code> and <code>compact!</code> methods.</li>
</ul>
<p>It behaves the same as <code>compact</code> and <code>compact!</code> methods of <code>Array</code> and <code>Hash</code> as follows.</p>
<p><code>Set#compact!</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Removes all nil elements from self. Returns self if any elements removed, otherwise nil.</span>
<span class="n">set</span> <span class="o">=</span> <span class="no">Set</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">,</span> <span class="kp">nil</span><span class="p">]</span> <span class="c1">#=> #<Set: {1, "c", nil}></span>
<span class="n">set</span><span class="p">.</span><span class="nf">compact!</span> <span class="c1">#=> #<Set: {1, "c"}></span>
<span class="n">set</span> <span class="c1">#=> #<Set: {1, "c"}></span>
<span class="n">set</span> <span class="o">=</span> <span class="no">Set</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">]</span> <span class="c1">#=> #<Set: {1, "c"}></span>
<span class="n">set</span><span class="p">.</span><span class="nf">compact!</span> <span class="c1">#=> nil</span>
<span class="n">set</span> <span class="c1">#=> #<Set: {1, "c"}></span>
</code></pre>
<p><code>Set#compact</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Returns a new Set containing all non-nil elements from self.</span>
<span class="n">set</span> <span class="o">=</span> <span class="no">Set</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">,</span> <span class="kp">nil</span><span class="p">]</span> <span class="c1">#=> #<Set: {1, "c", nil}></span>
<span class="n">set</span><span class="p">.</span><span class="nf">compact</span> <span class="c1">#=> #<Set: {1, "c"}></span>
<span class="n">set</span> <span class="c1">#=> #<Set: {1, "c", nil}></span>
<span class="n">set</span> <span class="o">=</span> <span class="no">Set</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="s1">'c'</span><span class="p">]</span> <span class="c1">#=> #<Set: {1, "c"}></span>
<span class="n">set</span><span class="p">.</span><span class="nf">compact</span> <span class="c1">#=> #<Set: {1, "c"}></span>
<span class="n">set</span> <span class="c1">#=> #<Set: {1, "c"}></span>
</code></pre>
<p>Pull Request ... <a href="https://github.com/ruby/ruby/pull/3617" class="external">https://github.com/ruby/ruby/pull/3617</a></p> 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 #17134 (Open): Add resolv_timeout to TCPSockethttps://bugs.ruby-lang.org/issues/171342020-08-29T05:26:59ZGlass_saga (Masaki Matsushita)glass.saga@gmail.com
<p>Add resolve_timeout to TCPSocket.new.<br>
It makes DNS timeout customizable in the same way as Socket.tcp.</p>
<p><a href="https://github.com/ruby/ruby/pull/3472" class="external">https://github.com/ruby/ruby/pull/3472</a></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 #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 #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 - Feature #15571 (Open): Add methods: iroot, root, and roots https://bugs.ruby-lang.org/issues/155712019-01-29T17:35:35Zjzakiya (Jabari Zakiya)
<p><strong>Proposal</strong><br>
The rubygem <code>roots</code> provides a few methods to find the numerical roots<br>
of real, complex, and integer numbers. This proposal requests including the<br>
following three (3) methods into Ruby.</p>
<p><a href="https://rubygems.org/gems/roots" class="external">https://rubygems.org/gems/roots</a><br>
<a href="https://github.com/jzakiya/roots" class="external">https://github.com/jzakiya/roots</a></p>
<p><code>iroot</code>: provide the accurate integer nth root value of any size integer</p>
<pre><code>2.6.0 :002 > require 'roots'
=> true
2.6.0 :010 > n = 12345678901234567890
=> 12345678901234567890
2.6.0 :011 > Integer.sqrt n
=> 3513641828
2.6.0 :012 > n.iroot 2
=> 3513641828
2.6.0 :013 > n.iroot 3
=> 2311204
2.6.0 :014 > n.iroot 4
=> 59275
</code></pre>
<p><code>root</code>: provide the accurate real value nth root of a real, complex, or integer numbers<br>
<code>roots</code>: provide a collection of all real|complex nth values</p>
<pre><code>2.6.0 :020 > n = 12345678901234567890
=> 12345678901234567890
2.6.0 :021 > Math.sqrt n
=> 3513641828.820144
2.6.0 :022 > n**(0.5)
=> 3513641828.820144
2.6.0 :023 > n.root 2
=> 3513641828.820144
2.6.0 :024 > n**(1.0/3)
=> 2311204.2409018343
2.6.0 :025 > n.root 3
=> 2311204.24090183
2.6.0 :026 > n.root 3,1
=> (2311204.24090183+0.0i)
2.6.0 :027 > n.root 3,2
=> (-1155602.12045092+2001561.58595532i)
2.6.0 :028 > n.root 3,3
=> (-1155602.12045092-2001561.58595532i)
2.6.0 :029 > n.roots 3
=> [(2311204.24090183+0.0i), (-1155602.12045092+2001561.58595532i), (-1155602.12045092-2001561.58595532i)]
2.6.0 :031 > n.roots 3, :real
=> [(2311204.24090183+0.0i)]
2.6.0 :032 > n.roots 3, :complex
=> [(-1155602.12045092+2001561.58595532i), (-1155602.12045092-2001561.58595532i)]
2.6.0 :033 > n.roots 3, :odd
=> [(2311204.24090183+0.0i), (-1155602.12045092-2001561.58595532i)]
2.6.0 :034 > n.roots 3, :even
=> [(-1155602.12045092+2001561.58595532i)]
2.6.0 :035 > (247823 + 398439i).root 4
=> (25.33541017+6.56622124i)
2.6.0 :036 > (247823 + 398439i).roots 4
=> [(25.33541017+6.56622124i), (-6.56622124+25.33541017i), (-25.33541017-6.56622124i), (6.56622124-25.33541017i)]
</code></pre>
<p><strong>Motivation</strong><br>
Ruby 2.5 included the method <code>Integer.sqrt</code>. It accurately returns the<br>
integer squareroot of integers, whereas performing <code>Math.sqrt(n).floor</code><br>
produced rounding errows once n exceeded a certain threshold.</p>
<p>Whereas <code>Integer.srt</code> solved that problem for squareroots, the same problem<br>
exists for the other nth roots when n reaches a certain (large) value too.<br>
Adding <code>iroot</code> completes providing this functionality for all nth roots.</p>
<p>Adding <code>root</code> and <code>roots</code> adds funcitionality either not currently present<br>
and/or provides it in an easier to use, standard, and more flexible manner.</p>
<p>I created the <code>roots</code> gem to help me do Project Euler (<a href="https://projecteuler.net/" class="external">https://projecteuler.net/</a>) problems.<br>
To probably most people|programmers, Ruby is primarily associated with web<br>
development through frameworks like Rails, Sinatra, Hanami, etc. However Ruby<br>
has great utility in math and numerical analysis fields. These methods provide<br>
basic arithmetic primitives upon which higher order functions can be created<br>
without the need to search for third-party packages. They will increase Ruby's<br>
footprint into numerical|analysis fields now dominated by Python and Julia.</p>
<p><strong>Pros</strong></p>
<ul>
<li>only 3 methods with no dependices</li>
<li>fast and numerically accurate (can change shown digits for <code>root(s)</code>
</li>
<li>adds previously unavailable functionality</li>
<li>provides existing funcionality in an easier to use, standard, and flexible manner</li>
<li>provides more math primitives to create higher order algorithms</li>
<li>makes Ruby, out-of-the-box, more useful for doing math, cryptography, etc</li>
<li>enhances Ruby's reputation as a more math friendly language</li>
<li>makes programmers doing math Happy! :-)</li>
</ul>
<p><strong>Cons</strong></p>
<ul>
<li>it adds 3 methods to language core</li>
<li>better names(?)</li>
</ul> 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 - Feature #15217 (Open): Add Resolv.current_resolverhttps://bugs.ruby-lang.org/issues/152172018-10-08T23:18:29Zchristophe971 (Christophe Maximin)
<p>This allows us to have a per-thread default resolver.<br>
This change is backwards compatible and will not change the behavior of Resolv.<br>
This commit is also adding a bunch of missing specs for Resolv.</p>
<p><a href="https://github.com/ruby/ruby/pull/1978" class="external">https://github.com/ruby/ruby/pull/1978</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 #14833 (Open): Add RubyVM::AST::Node#pretty_printhttps://bugs.ruby-lang.org/issues/148332018-06-07T14:44:15Zpocke (Masataka Kuwabara)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>This patch adds <code>RubyVM::AST::Node#pretty_print</code> for <code>pp</code>.</p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p><code>RubyVM::AST::Node#inspect</code> does not print children, so I cannot understand structure of a ast by <code>p</code> method.<br>
For example:</p>
<pre><code>$ ruby -e 'p RubyVM::AST.parse("if cond then foo; bar else hoge; fuga end")'
#<RubyVM::AST::Node(NODE_SCOPE(0) 1:0, 1:41): >
</code></pre>
<p>It is not understandable.</p>
<p>BTW parser gem prints children.</p>
<pre><code>$ ruby -rparser/current -e 'p Parser::CurrentRuby.parse("if cond then foo; bar else hoge; fuga end")'
s(:if,
s(:send, nil, :cond),
s(:begin,
s(:send, nil, :foo),
s(:send, nil, :bar)),
s(:begin,
s(:send, nil, :hoge),
s(:send, nil, :fuga)))
</code></pre>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>Add <code>RubyVM::AST::Node#pretty_print</code> for <code>pp</code> method and it displays children nodes.</p>
<pre><code>$ ruby -e 'p RubyVM::AST.parse("if cond then foo; bar else hoge; fuga end")'
#<RubyVM::AST::Node(NODE_SCOPE(0) 1:0, 1:41): >
$ ruby -e 'pp RubyVM::AST.parse("if cond then foo; bar else hoge; fuga end")'
#<RubyVM::AST::Node(NODE_SCOPE(0) 1:0, 1:41
nil,
#<RubyVM::AST::Node(NODE_IF(2) 1:0, 1:41
#<RubyVM::AST::Node(NODE_VCALL(38) 1:3, 1:7 ): >,
#<RubyVM::AST::Node(NODE_BLOCK(1) 1:13, 1:21
#<RubyVM::AST::Node(NODE_VCALL(38) 1:13, 1:16 ): >,
#<RubyVM::AST::Node(NODE_VCALL(38) 1:18, 1:21 ): >): >,
#<RubyVM::AST::Node(NODE_BLOCK(1) 1:27, 1:37
#<RubyVM::AST::Node(NODE_VCALL(38) 1:27, 1:31 ): >,
#<RubyVM::AST::Node(NODE_VCALL(38) 1:33, 1:37 ): >): >): >): >
</code></pre>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p>See <code>ast_node_pp.patch</code> from the attachment.</p>
<a name="Note"></a>
<h1 >Note<a href="#Note" class="wiki-anchor">¶</a></h1>
<p>Probably this format of <code>pp</code> is not the best. We can improve the format. For example, maybe we can add braces for children node.<br>
If you have any ideas, please tell me the ideas!</p> Ruby master - Feature #14777 (Open): Add Range#offset ?https://bugs.ruby-lang.org/issues/147772018-05-19T09:22:10Zowst (Owen Stephens)
<p>Hi,</p>
<p>As mentioned in <a href="https://bugs.ruby-lang.org/issues/14473#note-17" class="external">https://bugs.ruby-lang.org/issues/14473#note-17</a> an addition to Range that we find useful is an <code>Range#offset(n)</code> method that adds (or subtracts) <code>n</code> to the range, for example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">).</span><span class="nf">offset</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># => (3..12)</span>
<span class="p">(</span><span class="mi">1</span><span class="o">...</span><span class="mi">10</span><span class="p">).</span><span class="nf">offset</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span> <span class="c1"># => (2...11)</span>
<span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">).</span><span class="nf">offset</span><span class="p">(</span><span class="o">-</span><span class="mi">10</span><span class="p">)</span> <span class="c1"># => (-9..0)</span>
</code></pre>
<p>Similarly to <code>Range#step</code> we can support non-Numeric objects if they implement <code>succ</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="s1">'a'</span><span class="o">..</span><span class="s1">'e'</span><span class="p">).</span><span class="nf">offset</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># => ('c'..'g')</span>
</code></pre>
<p>Alternative names could be <code>Range#shift</code> (i.e. shift the elements of the Range up or down) or perhaps <code>>></code>/<code><<</code>:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">).</span><span class="nf">shift</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># => (3..12)</span>
<span class="p">(</span><span class="mi">1</span><span class="o">..</span><span class="mi">10</span><span class="p">)</span> <span class="o">>></span> <span class="mi">2</span> <span class="c1"># => (3..12)</span>
<span class="p">(</span><span class="mi">1</span><span class="o">...</span><span class="mi">10</span><span class="p">)</span> <span class="o"><<</span> <span class="mi">1</span> <span class="c1"># => (0...9)</span>
</code></pre>
<p>However, I don't think the operators are clear enough, so I prefer <code>offset</code> or <code>shift</code>.</p>
<p>An example pure Ruby implementation is:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Range</span>
<span class="k">def</span> <span class="nf">offset</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="n">add_n</span> <span class="o">=</span> <span class="o">-></span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">x</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Numeric</span><span class="p">)</span>
<span class="n">x</span> <span class="o">+</span> <span class="n">n</span>
<span class="k">elsif</span> <span class="n">x</span><span class="p">.</span><span class="nf">respond_to?</span><span class="p">(</span><span class="ss">:succ</span><span class="p">)</span>
<span class="n">n</span><span class="p">.</span><span class="nf">times</span> <span class="p">{</span> <span class="n">x</span> <span class="o">=</span> <span class="n">x</span><span class="p">.</span><span class="nf">succ</span> <span class="p">}</span>
<span class="n">x</span>
<span class="k">else</span>
<span class="k">raise</span> <span class="no">ArgumentError</span><span class="p">,</span> <span class="s2">"Can't offset </span><span class="si">#{</span><span class="n">x</span><span class="p">.</span><span class="nf">class</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">if</span> <span class="n">exclude_end?</span>
<span class="p">(</span><span class="n">add_n</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">first</span><span class="p">)</span><span class="o">...</span><span class="n">add_n</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">last</span><span class="p">))</span>
<span class="k">else</span>
<span class="p">(</span><span class="n">add_n</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">first</span><span class="p">)</span><span class="o">..</span><span class="n">add_n</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">last</span><span class="p">))</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>Please let me know your thoughts, I can then look to implement this properly in C.</p>
<p>Regards,<br>
Owen.</p> Ruby master - Feature #14771 (Open): Add method to create DNS resource from data stringhttps://bugs.ruby-lang.org/issues/147712018-05-17T12:34:45Zioquatix (Samuel Williams)samuel@oriontransfer.net
<p>I recently played around with DNS over HTTPS.</p>
<p>I found that it's a little bit tricky to generate the appropriate resource using the Resolv::DNS::Resource hierarchy.</p>
<p>Here is what my code ended up:</p>
<pre><code> if klass = Resolv::DNS::Resource.get_class(answer["type"], resource_class::ClassValue)
if klass < Resolv::DNS::Resource::DomainName
resource = klass.new(Resolv::DNS::Name.create(answer["data"]))
else
resource = klass.new(answer["data"])
end
</code></pre>
<p>It would be nice to have a simpler interface, e.g.</p>
<pre><code> if klass = Resolv::DNS::Resource.get_class(answer["type"], resource_class::ClassValue)
klass.create(answer["data"])
end
</code></pre>
<p>In this case, the <code>Resource#create</code> method would take a data string and convert it to a name if required.</p>
<p>The base resource class could just have <code>alias create new</code>, while the <code>DomainName</code> class could have:</p>
<pre><code>def create(data)
self.new(Name.create(data))
end
</code></pre>
<p>Or something like that.</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 #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 #13765 (Open): Add Proc#bindhttps://bugs.ruby-lang.org/issues/137652017-07-24T21:04:44Zdavidcornu (David Cornu)
<p><code>Proc</code> has <a href="https://ruby-doc.org/core-2.4.1/Proc.html#method-i-curry" class="external"><code>curry</code></a> but no method to do <a href="https://en.wikipedia.org/wiki/Partial_application" class="external">partial application</a>. Something like <code>Proc#bind</code> might be handy.</p>
<p>A naive implementation might look something like</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">Proc</span>
<span class="k">def</span> <span class="nf">bind</span><span class="p">(</span><span class="o">*</span><span class="n">bound_args</span><span class="p">)</span>
<span class="o">-></span> <span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">)</span> <span class="p">{</span> <span class="nb">self</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="o">*</span><span class="n">bound_args</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span> <span class="p">}</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<pre><code class="text syntaxhl" data-language="text">irb(main):001:0> foo = -> (first, second) { puts first, second }
=> #<Proc:0x007fc93a091f90@(irb):6 (lambda)>
irb(main):002:0> foo.bind(1).call(2)
1
2
=> nil
irb(main):003:0> foo.bind(1).bind(2).call
1
2
</code></pre>
<p>which does the job with the downside of only reporting argument mismatches when the returned <code>Proc</code> is called.</p>
<pre><code>irb(main):004:0> foo3 = foo.bind(1).bind(2).bind(3)
=> #<Proc:0x007fc9378bcb00@(irb):3 (lambda)>
irb(main):005:0> foo.call
ArgumentError: wrong number of arguments (given 0, expected 2)
from (irb):6:in `block in irb_binding'
from (irb):35
from /usr/local/bin/irb:11:in `<main>'
</code></pre> Ruby master - Feature #13639 (Open): Add "RTMIN" and "RTMAX" to Signal.listhttps://bugs.ruby-lang.org/issues/136392017-06-08T05:22:29Zksss (Yuki Kurihara)co000ri@gmail.com
<p>I propose to add the key "RTMIN" and "RTMAX" to Signal.list</p>
<p>Currently, We can't know signal number for realtime-signal at own environment in Ruby.<br>
And it's not potable if hard code number literal.</p>
<p>So, How about this idea?</p>
<p>Use case:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">unless</span> <span class="no">Signal</span><span class="p">.</span><span class="nf">list</span><span class="p">[</span><span class="s2">"RTMIN"</span><span class="p">]</span>
<span class="k">raise</span> <span class="s2">"realtime-signal does not supported"</span>
<span class="k">end</span>
<span class="no">MY_SIGNAL</span> <span class="o">=</span> <span class="no">Signal</span><span class="p">.</span><span class="nf">list</span><span class="p">[</span><span class="s2">"RTMIN"</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span>
<span class="no">Signal</span><span class="p">.</span><span class="nf">trap</span><span class="p">(</span><span class="no">MY_SIGNAL</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span>
<span class="nb">puts</span> <span class="s2">"Hello MY_SIGNAL"</span>
<span class="k">end</span>
<span class="no">Process</span><span class="p">.</span><span class="nf">kill</span><span class="p">(</span><span class="no">MY_SIGNAL</span><span class="p">,</span> <span class="vg">$$</span><span class="p">)</span>
<span class="c1">#=> "Hello MY_SIGNAL"</span>
</code></pre>
<p>Patch:</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">diff --git a/signal.c b/signal.c
index 8ee0963b8a..f17836350a 100644
</span><span class="gd">--- a/signal.c
</span><span class="gi">+++ b/signal.c
</span><span class="p">@@ -1381,6 +1381,12 @@</span> sig_list(void)
for (sigs = siglist; sigs->signm; sigs++) {
rb_hash_aset(h, rb_fstring_cstr(sigs->signm), INT2FIX(sigs->signo));
}
<span class="gi">+#ifdef SIGRTMIN
+ rb_hash_aset(h, rb_fstring_cstr("RTMIN"), INT2FIX(SIGRTMIN));
+#endif
+#ifdef SIGRTMAX
+ rb_hash_aset(h, rb_fstring_cstr("RTMAX"), INT2FIX(SIGRTMAX));
+#endif
</span> return h;
}
</code></pre>
<p>Inspired by <a href="https://github.com/ksss/mruby-signal/pull/3" class="external">https://github.com/ksss/mruby-signal/pull/3</a> and @takumakume</p> 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 #11917 (Open): Add Range#length as an alias for sizehttps://bugs.ruby-lang.org/issues/119172015-12-29T00:26:17Zdougo (Doug Orleans)dougorleans@gmail.com
<p>I noticed that <code>Range</code> has a <code>size</code> method but no <code>length</code>, unlike most other <code>Enumerable</code> classes. I propose adding <code>Range#length</code> as an alias for <code>Range#size</code>. Any reason not to?</p> 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 #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 #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 #9779 (Open): Add Module#descendentshttps://bugs.ruby-lang.org/issues/97792014-04-28T07:02:06Zshugo (Shugo Maeda)
<p>Now classes have links to their subclasses, so how about to add Module#descendents?</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">X</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Y</span> <span class="o"><</span> <span class="no">X</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Z</span> <span class="o"><</span> <span class="no">Y</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="no">X</span><span class="p">.</span><span class="nf">descendents</span> <span class="c1">#=> [X, Y, Z]</span>
<span class="k">module</span> <span class="nn">A</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">B</span>
<span class="kp">include</span> <span class="no">A</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">C</span>
<span class="kp">include</span> <span class="no">A</span>
<span class="k">end</span>
<span class="nb">p</span> <span class="no">A</span><span class="p">.</span><span class="nf">descendents</span> <span class="c1">#=> [A, C, B]</span>
</code></pre>
<p>One of my own use cases is to implement AspectJ like pointcut which matches all subclasses of the given class.</p>
<p>Considerations:</p>
<ul>
<li>Should the return value of Module#descendents include self?</li>
<li>Should the return value of Module#descendents include singleton classes?</li>
</ul>
<p>I attach a patch, where the return value includes both self and singleton classes.</p> Ruby master - Feature #9585 (Open): Add Object#in? to make ruby easier to readhttps://bugs.ruby-lang.org/issues/95852014-03-01T11:43:17Zsowieso (So Wieso)sowieso@dukun.de
<p>Please add an in? method to all objects, that allows the following:<br>
<code>4.in? 1,2,3,4 4.in? 1..4 "a".in? "abc" 7.in? 0..2, 5..8 3.in? small_numbers.select(&:odd?) =>true</code><br>
Background:<br>
Since my first steps in ruby it always bugs me, that using Array#include? to perform multiple checks in one line breaks symmetry, forces me to read backward and thus lets me stumble in the head. Ruby tries to be close to natural language, and therefore the subject should stand on the left side. Example:<br>
<code>if status == 1 if status == 1 or status == 2 if [1,2,127].include? status # breaks symmetry if status.in? 1, 2, 127 # better</code></p>
<p>Pros:<br>
‣ Nicer to read, no need to read the line backward (brings joy to writers and readers)<br>
‣ No new keyword<br>
‣ Breaks nothing</p>
<p>Cons:<br>
‣ One more method in Object<br>
‣ <code>"a".in? "abc", "def" vs "a".in? ["abc", "def"]</code> (implementation is yet an example)</p>
<p>Neutral:<br>
‣ Yet one more way to do it (isn't that ruby-style?)<br>
‣ Belongs to Object, as a comparison operator like ==, eql?, ===, nil?<br>
‣ “only cosmetics” vs elegance</p>
<p>Implementation for testing (you'd certainly find a less naive implementation):<br>
<code>class Object def in? *args raise ArgumentError if args.empty? args.any? {|a| a == self or a.include? self rescue false} end end</code><br>
This is related to <a href="https://bugs.ruby-lang.org/issues/3845" class="external">https://bugs.ruby-lang.org/issues/3845</a><br>
which was rejected for being an operator (even though the keyword already existed)</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 #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 #8994 (Open): add methods for Float to get if an NaN is quiet or not, also ...https://bugs.ruby-lang.org/issues/89942013-10-08T16:45:30ZHanmac (Hans Mackowiak)hanmac@gmx.de
<p>Currently its not easy possible to know of an NaN in ruby is silent or not</p>
<p>like Float::NAN.quiet?</p>
<p>there should also methods to make an new NaN like Float::quiet_nan, maybe with the possibility to set user data</p>
<p>also there is</p>
<p>[Float::NAN].pack("g") #=> "\x7F\xC0\x00\x00"<br>
[0.0/0.0].pack("g") #=> "\xFF\xC0\x00\x00"</p>
<p>and</p>
<p>[-(0.0/0.0)].pack("g") #=> "\x7F\xC0\x00\x00"</p>
<p>so it seems that - can turn an quiet NaN into an loud one? (i am not 100% clear about that)<br>
specially when using two different NaN in one operation like</p>
<p>[(0.0/0.0) + Float::NAN].pack("g") #=> "\xFF\xC0\x00\x00"<br>
[Float::NAN + (0.0/0.0)].pack("g") #=> "\x7F\xC0\x00\x00"</p>
<p>Wikipedia says:<br>
For example, a bit-wise IEEE floating-point standard single precision (32-bit) NaN would be: s111 1111 1axx xxxx xxxx xxxx xxxx xxxx where s is the sign (most often ignored in applications), a determines the type of NaN, and x is an extra payload (most often ignored in applications). If a = 1, it is a quiet NaN; if a is zero and the payload is nonzero, then it is a signaling NaN.</p>
<p>so it seems that the negation does it a bit wrong? i mean -@ should not change the value like that?</p> Ruby master - Feature #8751 (Open): Add offsets to method#source_locationhttps://bugs.ruby-lang.org/issues/87512013-08-08T14:03:29Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Hello,</p>
<p>I would like to have byte offsets returned on the source_location for methods. For example:</p>
<p>def foo(&b)<br>
b.source_location # => [file_name, line_number, start_byte, end_byte]<br>
end</p>
<p>If we had the start and end byte for a method or proc, then we could find the source for methods and procs in each file. There are some cases (like with heredocuments) where the "end of the method" could be after the <code>end</code> keyword. But I think if we just have offsets for the start of <code>def</code> and the end of <code>end</code>, I think it would cover 99% of usecases.</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 #8275 (Open): Add Module#public_const_gethttps://bugs.ruby-lang.org/issues/82752013-04-16T18:28:56Zrkh (Konstantin Haase)me@rkh.im
<p>Right now, <code>const_get</code> will always return a constant, no matter the visibility, which is probably what we want most of the time. But if you for instance have code that does some automatic name to constant resolution, you might now want to leak private constants.</p>
<p>module Foo<br>
Bar = 42<br>
private_constant :Bar<br>
end</p>
<a name="currently"></a>
<h1 >currently:<a href="#currently" class="wiki-anchor">¶</a></h1>
<p>Foo::Bar # raises NameError<br>
Foo.const_get("Bar") # => 42<br>
Object.const_get("Foo::Bar") # => 42</p>
<a name="proposed"></a>
<h1 >proposed:<a href="#proposed" class="wiki-anchor">¶</a></h1>
<p>Foo.public_const_get("Bar") # raises NameError<br>
Object.public_const_get("Foo::Bar") # raises NameError</p>