Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17097754782024-02-28T04:01:37ZRuby Issue Tracking System
Redmine Ruby master - Bug #20310 (Assigned): ASAN fake stacks need to be marked during GC for non-current...https://bugs.ruby-lang.org/issues/203102024-02-28T04:01:37Zkjtsanaktsidis (KJ Tsanaktsidis)kjtsanaktsidis@gmail.com
<p>When ASAN (address sanitizer) is enabled, the compiler does not necessarily store all local variables on the real machine stack; instead, locals can be stored in per-frame heap allocated memory which ASAN uses to detect things like stack-use-after-return ("fake stacks"). A pointer to the fake stack is left on the real machine stack, so it's possible to discover these fake stacks during GC and mark locals stored there as well.</p>
<p>At the moment, Ruby is currently marking these fake stacks for the current execution context which triggered GC, as part of <code>mark_current_machine_context</code>: <a href="https://github.com/ruby/ruby/blob/fe0b704df5553bdd59e90650ffbbfac785a2e48a/gc.c#L6411" class="external">https://github.com/ruby/ruby/blob/fe0b704df5553bdd59e90650ffbbfac785a2e48a/gc.c#L6411</a>. However, there are other machine stacks which also need to be marked like this:</p>
<ul>
<li>Machine stacks for other threads which did not trigger GC are marked in <code>rb_execution_context_mark</code> here: <a href="https://github.com/ruby/ruby/blob/fe0b704df5553bdd59e90650ffbbfac785a2e48a/vm.c#L3422" class="external">https://github.com/ruby/ruby/blob/fe0b704df5553bdd59e90650ffbbfac785a2e48a/vm.c#L3422</a>
</li>
<li>Machine stacks for fibers are marked in <code>cont_mark</code> here: <a href="https://github.com/ruby/ruby/blob/fe0b704df5553bdd59e90650ffbbfac785a2e48a/cont.c#L1030" class="external">https://github.com/ruby/ruby/blob/fe0b704df5553bdd59e90650ffbbfac785a2e48a/cont.c#L1030</a>
</li>
</ul>
<p>We need to make these two kinds of stacks perform the same ASAN fake stack marking as <code>mark_current_machine_context</code> does.</p>
<p>(P.S. - <code>callcc</code> continuations are another kind of machine stack which get marked, but ASAN is not compatible with callcc, so this doesn't really matter).</p>
<p>(P.S. - it appears to me that the currently-switched-to fiber will have its stack marked <em>twice</em>; once in <code>rb_execution_context_mark</code> or <code>mark_current_machine_context, and once in </code>cont_mark`; if this is true, I will fix this too)</p> Ruby master - Feature #20309 (Assigned): Bundled gems for Ruby 3.5https://bugs.ruby-lang.org/issues/203092024-02-27T22:16:20Zhsbt (Hiroshi SHIBATA)hsbt@ruby-lang.org
<p>I propose migrate the following default gems to bundled gems at Ruby 3.5. So, It means users will get warnings if users try to load them.</p>
<p>(Update with 2024/03/14)</p>
<ul>
<li>ostruct
<ul>
<li>I make ostruct as optional on json at <a href="https://github.com/flori/json/pull/565" class="external">https://github.com/flori/json/pull/565</a>
</li>
</ul>
</li>
<li>logger
<ul>
<li>activesupport needs to add logger to its dependency same as bigdecimal, drb or etc.</li>
</ul>
</li>
<li>fiddle</li>
<li>pstore</li>
<li>win32ole</li>
</ul>
<p>I have a plan to migrate the following default gems too. But I need to more feedback from other committers about them.</p>
<ul>
<li>irb
<ul>
<li>We need to consider how works <code>binding.irb</code> after Ruby 3.5.</li>
<li>I consider to use <code>irb</code> without Gemfile.</li>
</ul>
</li>
<li>reline</li>
<li>readline (wrapper file for readline-ext and reline)</li>
<li>io-console
<ul>
<li>rubygems uses that. Should we make optional that?</li>
</ul>
</li>
<li>open-uri</li>
<li>yaml (wrapper file for psych)
<ul>
<li>syck is retired today. I'm not sure what people uses <code>psych</code> directly, not <code>yaml</code>.</li>
</ul>
</li>
<li>rdoc
<ul>
<li>We need to change build task like download rdoc gem before document generation.
<ul>
<li>extract <code>make doc</code> from <code>make all</code> and invoke <code>make doc</code> before <code>make install</code>.</li>
</ul>
</li>
<li>or We make document generation is optional from Ruby 3.5
<ul>
<li>We explicitly separate <code>make install</code> and <code>make install-doc</code>
</li>
</ul>
</li>
</ul>
</li>
<li>un
<ul>
<li>
<code>ruby -run</code> is one of cool feature of Ruby. Should we avoid uninstalling <code>un</code> gem?</li>
<li>mkmf uses <code>ruby -run</code> for that. I need to investigate that.</li>
</ul>
</li>
<li>singleton
<ul>
<li>This is famous design pattern. Should we enforce users add them to their Gemfile?</li>
</ul>
</li>
<li>forwadable
<ul>
<li>
<code>reline</code> needs to add forwardable their <code>runtime_dependency</code> after migration.</li>
</ul>
</li>
<li>weakref
<ul>
<li>I'm not sure how impact after migrating bundled gems.</li>
</ul>
</li>
<li>fcntl
<ul>
<li>Should we integrate these constants into ruby core?</li>
</ul>
</li>
</ul>
<p>I would like to migrate <code>ipaddr</code> and <code>uri</code> too. But these are used by webrick that is mock server for our test suite. We need to rewrite <code>webrick</code> with <code>TCPSocker</code> or extract <code>ipaddr</code> and <code>uri</code> dependency from <code>webrick</code></p>
<p>Other default gems depend on our build process or other libraries deeply. I will update this proposal if I could extract them from default gems.</p> Ruby master - Bug #20146 (Assigned): Code using Ractor with env `RUBY_MAX_CPU=1` ends with unreac...https://bugs.ruby-lang.org/issues/201462024-01-04T02:17:54Zshia (Sangyong Sim)
<a name="Reproducible-code"></a>
<h2 >Reproducible code<a href="#Reproducible-code" class="wiki-anchor">¶</a></h2>
<pre><code class="rb syntaxhl" data-language="rb"><span class="c1"># sample-code.rb</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">new</span> <span class="p">{</span> <span class="mi">1</span> <span class="p">}</span>
</code></pre>
<pre><code class="bash syntaxhl" data-language="bash"><span class="nv">RUBY_MAX_CPU</span><span class="o">=</span>1 ruby sample-code.rb <span class="c"># This will not end with exit code 0</span>
<span class="nv">RUBY_MAX_CPU</span><span class="o">=</span>2 ruby sample-code.rb <span class="c"># This ends with exit code 0 as expected</span>
</code></pre>
<a name="Expected"></a>
<h2 >Expected<a href="#Expected" class="wiki-anchor">¶</a></h2>
<p>process with RUBY_MAX_CPU=1 exits successfully as same as RUBY_MAX_CPU more than 1.</p> Ruby master - Bug #19407 (Assigned): 2 threads taking from current ractor will hang foreverhttps://bugs.ruby-lang.org/issues/194072023-02-03T18:43:11Zluke-gru (Luke Gruber)luke.gru@gmail.com
<p>In the current implementation of Ractors, it's possible to <code>take</code> from the current ractor. This could be useful<br>
when co-ordinating threads:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span> <span class="c1"># do some work with obj</span>
<span class="k">end</span>
<span class="n">t0</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span> <span class="c1"># do some work with obj</span>
<span class="k">end</span>
<span class="no">Ractor</span><span class="p">.</span><span class="nf">yield</span> <span class="ss">:go</span>
</code></pre>
<p>However it hangs forever:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">t</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span>
<span class="k">end</span>
<span class="n">t0</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Ractor</span><span class="p">.</span><span class="nf">current</span><span class="p">.</span><span class="nf">take</span>
<span class="nb">p</span> <span class="n">obj</span>
<span class="k">end</span>
<span class="nb">sleep</span> <span class="mf">0.5</span>
</code></pre>
<p>Should "self-take" be disabled, or was it designed to allow it but this is just a bug?</p> Ruby master - Feature #19193 (Assigned): drop DOS TEXT mode supporthttps://bugs.ruby-lang.org/issues/191932022-12-09T16:38:20ZYO4 (Yoshinao Muramatsu)
<p>On Windows platform, <code>File.open(path, "r")</code> returns an object different from "rt" and "rb". I call that DOS TEXT mode here.</p>
<p>DOS TEXT mode does</p>
<ul>
<li>crlf conversion</li>
<li>0x1a treated EOF charactor on read</li>
</ul>
<p>and others (see Bug <a class="issue tracker-1 status-1 priority-4 priority-default" title="Bug: IO has third data mode, document is incomplete. (Open)" href="https://bugs.ruby-lang.org/issues/19192">#19192</a>).<br>
But DOS TEXT mode is almost unnecessary today and it seems to introduce lot of code complexities.</p>
<p>Now there is less need for dos text mode</p>
<ul>
<li>Microsoft's most apps works without CRLF newline.</li>
<li>Creating a crlf text file today should be explicit. (but that is default mode on windows now)</li>
<li>Interpreting EOF charactor can cause trouble.</li>
</ul>
<p>I think it's time to consider dropping DOS TEXT mode.<br>
What challenges are there and what preparation is needed?</p> Ruby master - Feature #18773 (Assigned): deconstruct to receive a rangehttps://bugs.ruby-lang.org/issues/187732022-05-11T17:13:54Zkddnewton (Kevin Newton)kddnewton@gmail.com
<p>Currently when you're pattern matching against a hash pattern, <code>deconstruct_keys</code> receives the keys that are being matched. This is really useful for computing expensive hashes.</p>
<p>However, when you're pattern matching against an array pattern, you don't receive any information. So if the array is expensive to compute (for instance loading an array of database records), you have no way to bail out. It would be useful to receive a range signifying how many records the pattern is specifying. It would be used like the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">class</span> <span class="nc">ActiveRecord::Relation</span>
<span class="k">def</span> <span class="nf">deconstruct</span><span class="p">(</span><span class="n">range</span><span class="p">)</span>
<span class="p">(</span><span class="n">loaded?</span> <span class="o">||</span> <span class="n">range</span><span class="p">.</span><span class="nf">cover?</span><span class="p">(</span><span class="n">count</span><span class="p">))</span> <span class="p">?</span> <span class="n">records</span> <span class="p">:</span> <span class="kp">nil</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>It needs to be a range and not just a number to handle cases where <code>*</code> is used. You would use it like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">case</span> <span class="no">Person</span><span class="p">.</span><span class="nf">all</span>
<span class="k">in</span> <span class="p">[]</span>
<span class="s2">"No records"</span>
<span class="k">in</span> <span class="p">[</span><span class="n">person</span><span class="p">]</span>
<span class="s2">"Only </span><span class="si">#{</span><span class="n">person</span><span class="p">.</span><span class="nf">name</span><span class="si">}</span><span class="s2">"</span>
<span class="k">else</span>
<span class="s2">"Multiple people"</span>
<span class="k">end</span>
</code></pre>
<p>In this way, you wouldn't have to load the whole thing into memory to check if it pattern matched. The patch is here: <a href="https://github.com/ruby/ruby/pull/5905" class="external">https://github.com/ruby/ruby/pull/5905</a>.</p> Ruby master - Bug #18677 (Assigned): BigDecimal#power (**) returns FloatDomainError when passing ...https://bugs.ruby-lang.org/issues/186772022-04-04T09:27:59Zdorianmariefr (Dorian Marié)
<p>Example:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="no">BigDecimal</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span> <span class="o">**</span> <span class="no">BigDecimal</span><span class="p">(</span><span class="s2">"Infinity"</span><span class="p">)</span>
<span class="no">FloatDomainError</span><span class="p">:</span> <span class="no">Computation</span> <span class="n">results</span> <span class="k">in</span> <span class="s1">'Infinity'</span>
</code></pre>
<p>Maybe:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s2">"bigdecimal/util"</span>
<span class="k">class</span> <span class="nc">BigDecimal</span> <span class="o"><</span> <span class="no">Numeric</span>
<span class="k">def</span> <span class="nf">**</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">if</span> <span class="n">other</span><span class="p">.</span><span class="nf">infinite?</span> <span class="o">==</span> <span class="mi">1</span>
<span class="k">if</span> <span class="nb">self</span> <span class="o">></span> <span class="mi">1</span>
<span class="no">BigDecimal</span><span class="o">::</span><span class="no">INFINITY</span>
<span class="k">elsif</span> <span class="nb">self</span> <span class="o">==</span> <span class="mi">1</span>
<span class="nb">self</span>
<span class="k">elsif</span> <span class="nb">self</span> <span class="o">>=</span> <span class="mi">0</span>
<span class="no">BigDecimal</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">else</span>
<span class="n">power</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">else</span>
<span class="n">power</span><span class="p">(</span><span class="n">other</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">puts_and_eval</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">string</span>
<span class="nb">p</span> <span class="nb">eval</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">puts_and_eval</span> <span class="s2">"10 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"1 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"0.1 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"0 ** BigDecimal::INFINITY"</span>
<span class="n">puts_and_eval</span> <span class="s2">"-1 ** BigDecimal::INFINITY"</span>
</code></pre>
<p>Seems like ruby is doing very different things from math though</p> Ruby master - Feature #18450 (Assigned): Force break in prettyprinthttps://bugs.ruby-lang.org/issues/184502021-12-29T13:16:58Zfirasalkhalil (Firas al-Khalil)
<a name="Abstract"></a>
<h1 >Abstract<a href="#Abstract" class="wiki-anchor">¶</a></h1>
<p>Support force-breaking a group in the std's <a href="https://github.com/ruby/prettyprint" class="external">prettyprint</a></p>
<a name="Background"></a>
<h1 >Background<a href="#Background" class="wiki-anchor">¶</a></h1>
<p>There is a need to forcibly break a group and transform breakables into<br>
newlines. The library doesn't provide this possibility, directly, through<br>
its public API.</p>
<a name="Proposal"></a>
<h1 >Proposal<a href="#Proposal" class="wiki-anchor">¶</a></h1>
<p>Add a single convenience function to the library's public class <code>PrettyPrint</code></p>
<a name="Implementation"></a>
<h1 >Implementation<a href="#Implementation" class="wiki-anchor">¶</a></h1>
<p>An implementation was submitted to the project's github repository as a<br>
<a href="https://github.com/ruby/prettyprint/pull/2" class="external">pull request</a>.</p>
<p>Here's the patch:</p>
<pre><code>diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb
index 188c2e6..1d675a7 100644
--- a/lib/prettyprint.rb
+++ b/lib/prettyprint.rb
@@ -236,6 +236,14 @@ class PrettyPrint
end
end
+ # This says "force a line break here".
+ #
+ # It will force the current group's "breakables" to break.
+ def break
+ breakable
+ current_group.break
+ end
+
# Groups line break hints added in the block. The line break hints are all
# to be used or not.
#
diff --git a/test/test_prettyprint.rb b/test/test_prettyprint.rb
index 27e7198..cf889d1 100644
--- a/test/test_prettyprint.rb
+++ b/test/test_prettyprint.rb
@@ -518,4 +518,31 @@ End
end
+
+class Break < Test::Unit::TestCase # :nodoc:
+ def format()
+ PrettyPrint.format(''.dup) {|q|
+ q.group {
+ q.text 'abc'
+ q.breakable
+ q.text 'def'
+ q.group {
+ q.break
+ q.text 'ghi'
+ }
+ q.breakable
+ q.text 'jkl'
+ }
+ }
+ end
+
+ def test_00_04
+ expected = <<'End'.chomp
+abc def
+ghi jkl
+End
+ assert_equal(expected, format())
+ end
+end
+
</code></pre>
<a name="Evaluation"></a>
<h1 >Evaluation<a href="#Evaluation" class="wiki-anchor">¶</a></h1>
<p>It's a simple implementation with no caveats.</p>
<a name="Discussion"></a>
<h1 >Discussion<a href="#Discussion" class="wiki-anchor">¶</a></h1>
<p>Even though it's a simple functionality, and the implementation is straightforward,<br>
getting to this point is not that obvious. This is why it might be helpful for other<br>
users who face such a need.</p>
<p>Indeed, an issue was <a href="https://github.com/ruby/prettyprint/issues/1" class="external">opened</a> not so long ago,<br>
and the proposed solution worked but not quite as expected. The provided implementation<br>
works as expected without tampering with the API's internals, and it's proven in production<br>
environment.</p>
<a name="Summary"></a>
<h1 >Summary<a href="#Summary" class="wiki-anchor">¶</a></h1>
<p>This is a feature request for the <code>prettyprint</code> library: adding support for <em>force breaking</em><br>
a group. An implementation is provided as both a patch and a PR on github.</p> Ruby master - Bug #17882 (Assigned): bootstraptest/test_ractor.rb:224 segfaults on Cygwinhttps://bugs.ruby-lang.org/issues/178822021-05-22T16:03:35Zxtkoba (Tee KOBAYASHI)
<p>The attached test code is excerpted from <code>bootstraptest/test_ractor.rb:224</code>. This code causes a segmentation fault every time when run on <code>x86_64-cygwin</code>. There are at least 3 types of dying messages, as shown below.</p>
<p>I have no idea whether this is relevant to <a class="issue tracker-1 status-1 priority-4 priority-default" title="Bug: bootstraptest/test_ractor.rb:224 a random failing test with "The outgoing-port is already closed ... (Open)" href="https://bugs.ruby-lang.org/issues/17878">#17878</a>, which is an issue with the very same test code.</p>
<p>Type 1 (null pointer dereference):</p>
<pre><code>Thread 6 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 5368]
VM_CF_BLOCK_HANDLER (cfp=0x0) at ../vm.c:115
115 const VALUE *ep = VM_CF_LEP(cfp);
(gdb) bt
#0 VM_CF_BLOCK_HANDLER (cfp=0x0) at ../vm.c:115
#1 0x00007ff6acedb495 in rb_vm_frame_block_handler (cfp=<optimized out>) at ../vm.c:128
#2 0x00007ff6acdd954e in pass_passed_block_handler (ec=0x80012bba0) at ../eval_intern.h:17
#3 rb_obj_call_init_kw (obj=obj@entry=123145240968920, argc=argc@entry=1, argv=argv@entry=0xffd0ca08, kw_splat=kw_splat@entry=0) at ../eval.c:1724
#4 0x00007ff6ace3efc2 in rb_class_new_instance (argc=argc@entry=1, argv=argv@entry=0xffd0ca08, klass=klass@entry=123145300575160) at ../object.c:2192
#5 0x00007ff6acdd1c30 in rb_exc_new_str (etype=etype@entry=123145300575160, str=<optimized out>) at ../error.c:1123
#6 0x00007ff6acdd29ad in rb_vraise (exc=123145300575160, fmt=<optimized out>, ap=<optimized out>) at ../error.c:2922
#7 0x00007ff6acdd29e5 in rb_raise (exc=0, fmt=0x0) at ../error.c:2930
#8 0x00007ff6acdf90e8 in rb_io_check_initialized (fptr=0x0) at ../io.c:767
#9 rb_io_check_initialized (fptr=<optimized out>) at ../io.c:764
#10 0x00007ff6acdf90fb in rb_io_check_closed (fptr=0x0) at ../io.c:774
#11 0x00007ff6ace011ec in prep_stdio (f=0x18023acb8 <reent_data+1336>, fmode=fmode@entry=1, klass=123145300573360, klass@entry=140697440105184, path=path@entry=0x7ff6acf158e0 <prelude_table+2944> "<STDIN>") at ../io.c:8239
#12 0x00007ff6ace0122f in rb_io_prep_stdin () at ../io.c:8255
#13 0x00007ff6acebc980 in thread_start_func_2 (th=0x0, th@entry=0x80011cbf0, stack_start=stack_start@entry=0xffd0ccf8) at ../thread.c:801
#14 0x00007ff6acebd032 in thread_start_func_1 (th_ptr=<optimized out>) at ../thread_pthread.c:1035
#15 0x000000018016d45f in pthread::thread_init_wrapper(void*) () from target:/usr/bin/cygwin1.dll
#16 0x00000001800ddbba in pthread_wrapper () from target:/usr/bin/cygwin1.dll
#17 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
</code></pre>
<p>Type 2 (<code>rb_gc_mark()</code>: <code><address></code> is <code>T_ZOMBIE</code>):</p>
<pre><code>Thread 7 hit Breakpoint 1, rb_bug (fmt=0x7ff6acf1396a <stat_data_type+8138> "rb_gc_mark(): %p is T_ZOMBIE") at ../error.c:782
782 {
(gdb) bt
#0 rb_bug (fmt=0x7ff6acf1396a <stat_data_type+8138> "rb_gc_mark(): %p is T_ZOMBIE") at ../error.c:782
#1 0x00007ff6acdeae8f in gc_mark_children (objspace=objspace@entry=0x800053970, obj=obj@entry=123145240171400) at ../gc.c:6934
#2 0x00007ff6acdeafb0 in gc_mark_stacked_objects (objspace=0x800053970, incremental=incremental@entry=0, count=count@entry=0) at ../gc.c:6961
#3 0x00007ff6acded415 in gc_mark_stacked_objects_all (objspace=0x800053970) at ../gc.c:7001
#4 gc_marks_rest (objspace=objspace@entry=0x800053970) at ../gc.c:7972
#5 0x00007ff6acdec08c in gc_marks (full_mark=<optimized out>, objspace=0x800053970) at ../gc.c:8028
#6 gc_start (objspace=objspace@entry=0x800053970, reason=<optimized out>, reason@entry=256) at ../gc.c:8862
#7 0x00007ff6acdee522 in heap_prepare (heap=0x800053998, objspace=0x800053970) at ../gc.c:2153
#8 heap_next_freepage (heap=0x800053998, objspace=0x800053970) at ../gc.c:2444
#9 ractor_cache_slots (objspace=objspace@entry=0x800053970, cr=cr@entry=0x800135d60) at ../gc.c:2476
#10 0x00007ff6acdee61a in newobj_slowpath (alloc_size=<optimized out>, wb_protected=0, cr=0x800135d60, objspace=0x800053970, flags=11, klass=123145300573360) at ../gc.c:2517
#11 newobj_slowpath_wb_unprotected (klass=123145300573360, flags=11, objspace=0x800053970, cr=0x800135d60, alloc_size=<optimized out>) at ../gc.c:2547
#12 0x00007ff6acdee815 in newobj_of0 (klass=klass@entry=123145300573360, flags=flags@entry=11, wb_protected=wb_protected@entry=0, cr=<optimized out>, alloc_size=<optimized out>) at ../gc.c:2585
#13 0x00007ff6acdee86d in newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, v1=v1@entry=0, v2=v2@entry=0, v3=v3@entry=0, wb_protected=wb_protected@entry=0, alloc_size=40) at ../gc.c:2594
#14 0x00007ff6acdeec23 in rb_wb_unprotected_newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, size=40, size@entry=0) at ../gc.c:2610
#15 0x00007ff6acdf666c in io_alloc (klass=klass@entry=123145300573360) at ../io.c:1038
#16 0x00007ff6acdfbca9 in prep_io (fd=2, fmode=fmode@entry=65546, klass=klass@entry=123145300573360, path=path@entry=0x7ff6acf158f1 <prelude_table+2961> "<STDERR>") at ../io.c:8206
#17 0x00007ff6ace011d4 in prep_stdio (f=0x18023ae28 <reent_data+1704>, fmode=fmode@entry=10, klass=123145300573360, klass@entry=34361007456, path=path@entry=0x7ff6acf158f1 <prelude_table+2961> "<STDERR>") at ../io.c:8237
#18 0x00007ff6ace01295 in rb_io_prep_stderr () at ../io.c:8267
#19 0x00007ff6acebc9a6 in thread_start_func_2 (th=0x0, th@entry=0x800134550, stack_start=stack_start@entry=0xffa0ccf8) at ../thread.c:803
#20 0x00007ff6acebd032 in thread_start_func_1 (th_ptr=<optimized out>) at ../thread_pthread.c:1035
#21 0x000000018016d45f in pthread::thread_init_wrapper(void*) () from target:/usr/bin/cygwin1.dll
#22 0x00000001800ddbba in pthread_wrapper () from target:/usr/bin/cygwin1.dll
#23 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
</code></pre>
<p>Type 3 (try to mark <code>T_NONE</code> object):</p>
<pre><code><OBJ_INFO:gc_mark_ptr@../gc.c:6580> 0x00006fffffe7fb70 [0 M ] T_NONE
------------------------------------------------------------------------
Thread 7 hit Breakpoint 1, rb_bug (fmt=fmt@entry=0x7ff6acf138a0 <stat_data_type+7936> "try to mark T_NONE object") at ../error.c:782
782 {
(gdb) bt
#0 rb_bug (fmt=fmt@entry=0x7ff6acf138a0 <stat_data_type+7936> "try to mark T_NONE object") at ../error.c:782
#1 0x00007ff6acdea5c9 in gc_mark_ptr (objspace=0x800053970, obj=123145300736880) at ../gc.c:6581
#2 0x00007ff6ace672ea in ractor_mark (ptr=0x800117240) at ../ractor.c:197
#3 0x00007ff6acdeafb0 in gc_mark_stacked_objects (objspace=objspace@entry=0x800053970, incremental=incremental@entry=1, count=count@entry=2147483647) at ../gc.c:6961
#4 0x00007ff6acded3f9 in gc_mark_stacked_objects_incremental (count=2147483647, objspace=0x800053970) at ../gc.c:6995
#5 gc_marks_rest (objspace=objspace@entry=0x800053970) at ../gc.c:7968
#6 0x00007ff6acdee4f1 in gc_marks_continue (heap=0x800053998, objspace=0x800053970) at ../gc.c:8012
#7 heap_prepare (heap=0x800053998, objspace=0x800053970) at ../gc.c:2148
#8 heap_next_freepage (heap=0x800053998, objspace=0x800053970) at ../gc.c:2444
#9 ractor_cache_slots (objspace=objspace@entry=0x800053970, cr=cr@entry=0x800129350) at ../gc.c:2476
#10 0x00007ff6acdee61a in newobj_slowpath (alloc_size=<optimized out>, wb_protected=0, cr=0x800129350, objspace=0x800053970, flags=11, klass=123145300573360) at ../gc.c:2517
#11 newobj_slowpath_wb_unprotected (klass=123145300573360, flags=11, objspace=0x800053970, cr=0x800129350, alloc_size=<optimized out>) at ../gc.c:2547
#12 0x00007ff6acdee815 in newobj_of0 (klass=klass@entry=123145300573360, flags=flags@entry=11, wb_protected=wb_protected@entry=0, cr=<optimized out>, alloc_size=<optimized out>) at ../gc.c:2585
#13 0x00007ff6acdee86d in newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, v1=v1@entry=0, v2=v2@entry=0, v3=v3@entry=0, wb_protected=wb_protected@entry=0, alloc_size=40) at ../gc.c:2594
#14 0x00007ff6acdeec23 in rb_wb_unprotected_newobj_of (klass=klass@entry=123145300573360, flags=flags@entry=11, size=40, size@entry=0) at ../gc.c:2610
#15 0x00007ff6acdf666c in io_alloc (klass=klass@entry=123145300573360) at ../io.c:1038
#16 0x00007ff6acdfbca9 in prep_io (fd=0, fmode=fmode@entry=65537, klass=klass@entry=123145300573360, path=path@entry=0x7ff6acf158e0 <prelude_table+2944> "<STDIN>") at ../io.c:8206
#17 0x00007ff6ace011d4 in prep_stdio (f=0x18023acb8 <reent_data+1336>, fmode=fmode@entry=1, klass=123145300573360, klass@entry=140697440105184, path=path@entry=0x7ff6acf158e0 <prelude_table+2944> "<STDIN>") at ../io.c:8237
#18 0x00007ff6ace0122f in rb_io_prep_stdin () at ../io.c:8255
#19 0x00007ff6acebc980 in thread_start_func_2 (th=0x0, th@entry=0x80010dcb0, stack_start=stack_start@entry=0xffa0ccf8) at ../thread.c:801
#20 0x00007ff6acebd032 in thread_start_func_1 (th_ptr=<optimized out>) at ../thread_pthread.c:1035
#21 0x000000018016d45f in pthread::thread_init_wrapper(void*) () from target:/usr/bin/cygwin1.dll
#22 0x00000001800ddbba in pthread_wrapper () from target:/usr/bin/cygwin1.dll
#23 0x0000000000000000 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
</code></pre> Ruby master - Misc #17720 (Assigned): Cirrus CI to check non-x86_64 architecture cases by own mac...https://bugs.ruby-lang.org/issues/177202021-03-12T17:50:05Zjaruga (Jun Aruga)
<p>Hello!</p>
<p>This ticket is related to the tickets <a class="issue tracker-5 status-5 priority-4 priority-default closed" title="Misc: Enabling ARM 64/32-bit cases by Drone CI (Closed)" href="https://bugs.ruby-lang.org/issues/16234">#16234</a> <a class="issue tracker-5 status-5 priority-4 priority-default closed" title="Misc: Enabling IBM PowerPC/Z cases in Travis CI (Closed)" href="https://bugs.ruby-lang.org/issues/16360">#16360</a>. But I opened a new ticket because it is related to general non-x86_64 architecture CI cases.</p>
<p>I have a suggestion.</p>
<p>I see the <code>.travis.yml</code> was removed [1], and I also saw another open source project remove their <code>.travis.yml</code> because they could not get the credits to continue to run Travis [2]. I feel Travis is not really a possible option for every open source project for now.</p>
<p>While we have RubyCI, I think we still have a motivation to run a CI on non-x86_64 architectures at a pull-request timing. So, I investigated alternative CI. When checking GitHub Actions, I do not feel it will happen soon on GitHub Actions [3]. Then I found an interesting CI called "Cirrus CI", that might enable us to run CI on non-x86_64 architectures such as Mac M1 (arm) ppc64le and s390x beyond the cloud.</p>
<p>Cirrus CI has 2 types of features: "cloud" and "persistent workers". I see the Cirrus CI "cloud" feature has been used in the QEMU and podman projects [4][5]. It has a unique freeBSD host. However the remarkable feature for the Ruby project is the "persistent workers" [6] announced a few months ago, that is beyond the cloud. Because this feature enables us to use our own machines as a CI running host. You can see the examples running the CI with the machines such as Mac M1, iPhone, ppc64le and s390x on the page [6]. Maybe the used machine does not even have the global static IP. You can see other articles [7][8] too.</p>
<p>I can see some benefits to start Cirrus CI for the Ruby project.</p>
<ul>
<li>Possibly we can check Mac M1 (arm), ppc64le, s390x cases using machines used in RubyCI [9] and someone's machine such as @ReiOdaira's ppc64le/s390x machines at the pull-request timing.</li>
<li>When we face the CI issue, we can login to the machine and use the interactive debugging tool such as gdb to fix it.</li>
<li>The config file is YAML format and it has the matrix feature [10]. We are familiar with the YAML and matrix.</li>
</ul>
<p>What do you think? Positive or negative?<br>
Thank you.</p>
<p>[1] ruby removed .travis.yml: <a href="https://github.com/ruby/ruby/commit/6b978d542704a5614af5e9375c4b31b8d2618652" class="external">https://github.com/ruby/ruby/commit/6b978d542704a5614af5e9375c4b31b8d2618652</a><br>
[2] simde removed .travis.yml: <a href="https://github.com/simd-everywhere/simde/commit/17a27e7f2c3114225899f2ace14010cbbb2139b5" class="external">https://github.com/simd-everywhere/simde/commit/17a27e7f2c3114225899f2ace14010cbbb2139b5</a><br>
[3] GitHub Actions and ppc64le: <a href="https://github.community/t/self-hosted-runner-on-ppc64el-architecture/155337" class="external">https://github.community/t/self-hosted-runner-on-ppc64el-architecture/155337</a><br>
[4] QEMU: <a href="https://gitlab.com/qemu-project/qemu/-/blob/master/.cirrus.yml" class="external">https://gitlab.com/qemu-project/qemu/-/blob/master/.cirrus.yml</a><br>
[5] Podman: <a href="https://github.com/containers/podman/blob/master/.cirrus.yml" class="external">https://github.com/containers/podman/blob/master/.cirrus.yml</a><br>
[6] The issue ticket of Persistent Workers: <a href="https://github.com/cirruslabs/cirrus-ci-docs/issues/263#issuecomment-746900845" class="external">https://github.com/cirruslabs/cirrus-ci-docs/issues/263#issuecomment-746900845</a><br>
[7] Persistent Workers blog: <a href="https://medium.com/cirruslabs/announcing-public-beta-of-cirrus-ci-persistent-workers-7327a38004be" class="external">https://medium.com/cirruslabs/announcing-public-beta-of-cirrus-ci-persistent-workers-7327a38004be</a><br>
[8] Persistent Workers guide: <a href="https://cirrus-ci.org/guide/persistent-workers/" class="external">https://cirrus-ci.org/guide/persistent-workers/</a><br>
[9] RubyCI: <a href="https://rubyci.org/" class="external">https://rubyci.org/</a><br>
[10] Cirrus CI matrix feature: <a href="https://cirrus-ci.org/guide/writing-tasks/#matrix-modification" class="external">https://cirrus-ci.org/guide/writing-tasks/#matrix-modification</a></p> Ruby master - Bug #17516 (Assigned): forking in a ractor causes Ruby to crashhttps://bugs.ruby-lang.org/issues/175162021-01-06T10:56:50Zpkmuldoon (Phil Muldoon)
<p>I just want to point out, there's absolutely no reason to do this, but</p>
<p>r = Ractor.new do<br>
Process.fork()<br>
end</p>
<p>Will cause:</p>
<p><a href="internal:ractor" class="external">internal:ractor</a>:267: warning: Ractor is experimental, and the behavior may change in future versions of Ruby! Also there are many implementation issues.<br>
[BUG] rb_thread_terminate_all: called by child thread (0x0000700004ddca40, 0x00007f981b567ee0)<br>
ruby 3.0.0p0 (2020-12-25 revision 95aff21468) [x86_64-darwin20]</p>
<p>-- Crash Report log information --------------------------------------------<br>
See Crash Report log file under the one of following:<br>
* ~/Library/Logs/DiagnosticReports<br>
* /Library/Logs/DiagnosticReports<br>
for more details.<br>
Don't forget to include the above Crash Report log file in bug reports.</p>
<p>-- Control frame information -----------------------------------------------<br>
c:0001 p:---- s:0003 e:000002 (none) [FINISH]</p>
<p>-- C level backtrace information -------------------------------------------<br>
=> #<Ractor:#3 (pry):5 terminated><br>
[4] pry(main)> /Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_vm_bugreport+0x6cf) [0x103084d1f]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_bug_without_die+0x206) [0x102e9e2b6]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_bug+0x71) [0x103091e6b]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_thread_terminate_all+0x329) [0x10301e5b9]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_ractor_terminate_all+0xa3) [0x102f8acc3]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(rb_ec_cleanup+0x229) [0x102ea9299]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(ruby_stop+0x9) [0x102ea9509]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(thread_start_func_2+0x8ce) [0x103027fce]<br>
/Users/phillipmuldoon/.rubies/ruby-3.0.0/bin/ruby(thread_start_func_1+0x10d) [0x10302753d]<br>
/usr/lib/system/libsystem_pthread.dylib(_pthread_start+0xe0) [0x7fff20382950]</p> Ruby master - Feature #17297 (Assigned): Feature: Introduce Pathname.mktmpdirhttps://bugs.ruby-lang.org/issues/172972020-10-30T15:09:41Zschneems (Richard Schneeman)
<p>When I want to create a tmpdir I often want to manipulate it as a pathname. By introducing Pathname.mktmpdir I can get this behavior.</p>
<p>Currently I must:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Dir</span><span class="p">.</span><span class="nf">mktmpdir</span> <span class="k">do</span> <span class="o">|</span><span class="n">dir</span><span class="o">|</span>
<span class="n">dir</span> <span class="o">=</span> <span class="no">Pathname</span><span class="p">(</span><span class="n">dir</span><span class="p">)</span>
<span class="c1"># ... code</span>
<span class="k">end</span>
</code></pre>
<p>I would like to be able to instead:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">mktmpdir</span> <span class="k">do</span> <span class="o">|</span><span class="n">dir</span><span class="o">|</span>
<span class="c1"># ... code</span>
<span class="k">end</span>
</code></pre>
<p>Diff:</p>
<pre><code>$ git diff master
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..ec32e7d611 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -597,3 +597,20 @@ def rmtree
end
end
+class Pathname # * tmpdir *
+ # Creates a tmp directory and wraps the returned path in a Pathname object.
+ #
+ # See Dir.mktmpdir
+ def self.mktmpdir
+ require 'tmpdir' unless defined?(Dir.mktmpdir)
+ if block_given?
+ Dir.mktmpdir do |dir|
+ dir = self.new(dir)
+ yield dir
+ end
+ else
+ self.new(Dir.mktmpdir)
+ end
+ end
+end
+
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..8edcccf666 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1272,6 +1272,14 @@ def test_s_glob_3args
}
end
+ def test_mktmpdir
+ Pathname.mktmpdir do |dir|
+ assert_equal Pathname(dir), dir
+ assert dir.directory?
+ assert dir.exist?
+ end
+ end
+
def test_s_getwd
wd = Pathname.getwd
assert_kind_of(Pathname, wd)
</code></pre>
<p>Github link: <a href="https://github.com/ruby/ruby/pull/3709" class="external">https://github.com/ruby/ruby/pull/3709</a></p> Ruby master - Feature #17296 (Assigned): Feature: Pathname#chmod use FileUtils.chmod instead of Filehttps://bugs.ruby-lang.org/issues/172962020-10-30T15:08:09Zschneems (Richard Schneeman)
<p>The <code>FileUtils.chmod</code> provides the same numerical interface as <code>File.chmod</code> and it also includes a "symbolic mode" interface. With this patch you'll be able to run this code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"bin/compile"</span><span class="p">).</span><span class="nf">chmod</span><span class="p">(</span><span class="s2">"+x"</span><span class="p">)</span>
</code></pre>
<p>I believe that this is backwards compatible with the existing implementation and all changes are an extension. The only difference between File.chmod and FileUtils.chmod I could find is they have different return values and the previous implementation of <code>Pathname#chmod</code> returned the result of the <code>File.chmod</code> call. From the docs <code>File.chmod</code> returns the number of files modified, since we're only ever able to pass in a maximum of one file through this interface, the return value will always be a <code>1</code> or an exception if the file does not exist.</p>
<p>I checked and the exceptions when the file does not exist match:</p>
<pre><code>irb(main):004:0> File.chmod(0444, "doesnotexist.txt")
Traceback (most recent call last):
6: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `<main>'
5: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `load'
4: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
3: from (irb):3
2: from (irb):4:in `rescue in irb_binding'
1: from (irb):4:in `chmod'
Errno::ENOENT (No such file or directory @ apply2files - doesnotexist.txt)
irb(main):005:0> FileUtils.chmod(0444, "doesnotexist.txt")
Traceback (most recent call last):
10: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `<main>'
9: from /Users/rschneeman/.rubies/ruby-2.7.2/bin/irb:23:in `load'
8: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
7: from (irb):4
6: from (irb):5:in `rescue in irb_binding'
5: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1016:in `chmod'
4: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1016:in `each'
3: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1017:in `block in chmod'
2: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1346:in `chmod'
1: from /Users/rschneeman/.rubies/ruby-2.7.2/lib/ruby/2.7.0/fileutils.rb:1346:in `chmod'
Errno::ENOENT (No such file or directory @ apply2files - doesnotexist.txt)
</code></pre>
<p>If you're open to changing the interface of the return value my preference would be to return <code>self</code> from this method so that it can be chained. Otherwise this current patch is a smaller change.</p>
<p>Diff:</p>
<pre><code>$ git diff master
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..cb6e32d9ac 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -585,6 +585,15 @@ def mkpath
nil
end
+ # Changes file permissions.
+ #
+ # See FileUtils.chmod
+ def chmod(mode)
+ require 'fileutils'
+ FileUtils.chmod(mode, self)
+ return 1
+ end
+
# Recursively deletes a directory, including all directories beneath it.
#
# See FileUtils.rm_r
diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c
index f71cec1b25..6778d4f102 100644
--- a/ext/pathname/pathname.c
+++ b/ext/pathname/pathname.c
@@ -12,7 +12,6 @@ static ID id_binwrite;
static ID id_birthtime;
static ID id_blockdev_p;
static ID id_chardev_p;
-static ID id_chmod;
static ID id_chown;
static ID id_ctime;
static ID id_directory_p;
@@ -552,20 +551,6 @@ path_mtime(VALUE self)
return rb_funcall(rb_cFile, id_mtime, 1, get_strpath(self));
}
-/*
- * call-seq:
- * pathname.chmod(mode_int) -> integer
- *
- * Changes file permissions.
- *
- * See File.chmod.
- */
-static VALUE
-path_chmod(VALUE self, VALUE mode)
-{
- return rb_funcall(rb_cFile, id_chmod, 2, mode, get_strpath(self));
-}
-
/*
* call-seq:
* pathname.lchmod(mode_int) -> integer
@@ -1448,7 +1433,6 @@ path_f_pathname(VALUE self, VALUE str)
* - #birthtime
* - #ctime
* - #mtime
- * - #chmod(mode)
* - #lchmod(mode)
* - #chown(owner, group)
* - #lchown(owner, group)
@@ -1495,6 +1479,7 @@ path_f_pathname(VALUE self, VALUE str)
* === Utilities
*
* These methods are a mixture of Find, FileUtils, and others:
+ * - #chmod(mode)
* - #find(&block)
* - #mkpath
* - #rmtree
@@ -1542,7 +1527,6 @@ Init_pathname(void)
rb_define_method(rb_cPathname, "birthtime", path_birthtime, 0);
rb_define_method(rb_cPathname, "ctime", path_ctime, 0);
rb_define_method(rb_cPathname, "mtime", path_mtime, 0);
- rb_define_method(rb_cPathname, "chmod", path_chmod, 1);
rb_define_method(rb_cPathname, "lchmod", path_lchmod, 1);
rb_define_method(rb_cPathname, "chown", path_chown, 2);
rb_define_method(rb_cPathname, "lchown", path_lchown, 2);
@@ -1618,7 +1602,6 @@ InitVM_pathname(void)
id_birthtime = rb_intern("birthtime");
id_blockdev_p = rb_intern("blockdev?");
id_chardev_p = rb_intern("chardev?");
- id_chmod = rb_intern("chmod");
id_chown = rb_intern("chown");
id_ctime = rb_intern("ctime");
id_directory_p = rb_intern("directory?");
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..5673691231 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -823,6 +823,11 @@ def test_chmod
path.chmod(0444)
assert_equal(0444, path.stat.mode & 0777)
path.chmod(old)
+
+ skip "Windows has different symbolic mode" if /mswin|mingw/ =~ RUBY_PLATFORM
+ path.chmod("u=wrx,g=rx,o=x")
+ assert_equal(0751, path.stat.mode & 0777)
+ path.chmod(old)
}
end
</code></pre>
<p>Github link: <a href="https://github.com/ruby/ruby/pull/3708" class="external">https://github.com/ruby/ruby/pull/3708</a></p> Ruby master - Feature #17295 (Assigned): Feature: Create a directory and file with Pathname#touchhttps://bugs.ruby-lang.org/issues/172952020-10-30T15:06:39Zschneems (Richard Schneeman)
<p>Right now if a developer wants to create a file and is not sure if the path exists yet or not they must:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"/a/b/c/d.txt"</span><span class="p">).</span><span class="nf">tap</span> <span class="p">{</span><span class="o">|</span><span class="nb">p</span><span class="o">|</span> <span class="nb">p</span><span class="p">.</span><span class="nf">dirname</span><span class="p">.</span><span class="nf">mkpath</span><span class="p">;</span> <span class="no">FileUtils</span><span class="p">.</span><span class="nf">touch</span><span class="p">(</span><span class="nb">p</span><span class="p">)}</span>
</code></pre>
<p>After this patch a developer can instead call:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="no">Pathname</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"/a/b/c/d.txt"</span><span class="p">).</span><span class="nf">touch</span>
</code></pre>
<p>An alternative name for this behavior could be <code>mkfile</code> but I think it is confusing to have a <code>mkfile</code> and a <code>mkpath</code> where one creates a directory and one creates a file.</p>
<p>Diff:</p>
<pre><code>$ git diff master
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..2ed02a6633 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -585,6 +585,27 @@ def mkpath
nil
end
+ # Creates a file and the full path to the file including any intermediate directories that don't yet
+ # exist.
+ #
+ # Example:
+ #
+ # Dir.exist?("/a/b/c") # => false
+ #
+ # p = Pathname.new("/a/b/c/d.txt")
+ # p.file? => false
+ # p.touch
+ # p.file? => true
+ #
+ # Dir.exist?("/a/b/c") # => true
+ def touch
+ require 'fileutils'
+ dirname.mkpath
+
+ FileUtils.touch(self)
+ self
+ end
+
# Recursively deletes a directory, including all directories beneath it.
#
# See FileUtils.rm_r
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..3c518cc3da 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1394,6 +1394,14 @@ def test_mkpath
}
end
+ def test_touch
+ with_tmpchdir('rubytest-pathname') {|dir|
+ Pathname("a/b/c/d.txt").touch
+ assert_file.directory?("a/b/c")
+ assert_file.file?("a/b/c/d.txt")
+ }
+ end
+
def test_rmtree
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
</code></pre>
<p>Github link: <a href="https://github.com/ruby/ruby/pull/3706" class="external">https://github.com/ruby/ruby/pull/3706</a></p> Ruby master - Feature #17294 (Assigned): Feature: Allow method chaining with Pathname#mkpath Path...https://bugs.ruby-lang.org/issues/172942020-10-30T15:04:06Zschneems (Richard Schneeman)
<p>Currently in my code when I want to create a pathname object and create a path at the same time I must use tap</p>
<pre><code>path = Pathname.new("/tmp/new").tap(&:mkpath)
</code></pre>
<p>I think it would be cleaner to be able to chain on the results of these methods instead:</p>
<pre><code>path = Pathname.new("/tmp/new").mkpath
</code></pre>
<p>This is a change in return value but after research on github I do not believe many (if any) are relying on the current behavior to return nil <a href="https://github.com/search?l=&p=1&q=.mkpath+language%3ARuby&ref=advsearch&type=Code" class="external">https://github.com/search?l=&p=1&q=.mkpath+language%3ARuby&ref=advsearch&type=Code</a>.</p>
<p>Here is my diff:</p>
<pre><code>$ git diff master schneems/return-self-pathname
diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb
index e6fb90277d..f1eb1e00ae 100644
--- a/ext/pathname/lib/pathname.rb
+++ b/ext/pathname/lib/pathname.rb
@@ -582,7 +582,7 @@ class Pathname # * FileUtils *
def mkpath
require 'fileutils'
FileUtils.mkpath(@path)
- nil
+ self
end
# Recursively deletes a directory, including all directories beneath it.
@@ -593,7 +593,7 @@ def rmtree
# File::Path provides "mkpath" and "rmtree".
require 'fileutils'
FileUtils.rm_r(@path)
- nil
+ self
end
end
diff --git a/test/pathname/test_pathname.rb b/test/pathname/test_pathname.rb
index 43cef4849f..149fe15c3a 100644
--- a/test/pathname/test_pathname.rb
+++ b/test/pathname/test_pathname.rb
@@ -1389,7 +1389,8 @@ def test_find
def test_mkpath
with_tmpchdir('rubytest-pathname') {|dir|
- Pathname("a/b/c/d").mkpath
+ path = Pathname("a/b/c/d")
+ assert_equal(path, path.mkpath)
assert_file.directory?("a/b/c/d")
}
end
@@ -1398,7 +1399,8 @@ def test_rmtree
with_tmpchdir('rubytest-pathname') {|dir|
Pathname("a/b/c/d").mkpath
assert_file.exist?("a/b/c/d")
- Pathname("a").rmtree
+ path = Pathname("a")
+ assert_equal(path, path.rmtree)
assert_file.not_exist?("a")
}
end
</code></pre>
<p>Github PR: <a href="https://github.com/ruby/ruby/pull/3705" class="external">https://github.com/ruby/ruby/pull/3705</a>. If accepted I will make a pr to update the tests here as well <a href="https://github.com/ruby/rbs/blob/b0dee64fdd00cc41c0729fa2c239fc2dcb9c3b18/test/stdlib/Pathname_test.rb#L456-L463" class="external">https://github.com/ruby/rbs/blob/b0dee64fdd00cc41c0729fa2c239fc2dcb9c3b18/test/stdlib/Pathname_test.rb#L456-L463</a>.</p> Ruby master - Misc #17137 (Assigned): Cooperation on maintaining official docker ruby imageshttps://bugs.ruby-lang.org/issues/171372020-08-31T19:52:31Zdeivid (David Rodríguez)
<p>It was pointed out to me at <a href="https://github.com/docker-library/ruby/issues/323" class="external">https://github.com/docker-library/ruby/issues/323</a> that the ruby-core team has started maintaining their own docker images at <a href="https://github.com/ruby/ruby-docker-images" class="external">https://github.com/ruby/ruby-docker-images</a>, and that the base Dockerfiles were initially started from the official docker images.</p>
<p>The maintainers of the official images would be interesting in collaborating on maintaining these images. Maybe merging the projects would be a nice idea from an end user point of view. I'm guessing there's a reason why <a href="https://github.com/ruby/ruby-docker-images" class="external">https://github.com/ruby/ruby-docker-images</a> was started as a separate project, but maybe any improvements over the official project could be merged back. The obvious new feature that I see in the README is the ability to build development images of specific revisions.</p>
<p>Anyways, I mentioned the approach of the docker folks to hsbt and he told me to open a ticket here. So here it is!</p>
<p>Regards!</p> Ruby master - Feature #16937 (Assigned): Add DNS over HTTP to Resolvhttps://bugs.ruby-lang.org/issues/169372020-06-07T23:46:44Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>This adds a DNS over HTTP resolver at Resolv::DoH</p>
<p>It obeys RFC8484 with respect to Cache-Control and Age behavior, but does not use HTTP2 as ruby does not have an HTTP2 client.</p>
<p>It does not allow configuration of the Net::HTTP instance beyond timeouts, but I am willing to add more configuration if this is desired.</p> Ruby master - Misc #16805 (Assigned): Coroutine's license is unclearhttps://bugs.ruby-lang.org/issues/168052020-04-21T10:23:49Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<p>Files under <code>coroutine/</code> start like this:</p>
<pre><code class="C syntaxhl" data-language="C"><span class="o">/*</span>
<span class="o">*</span> <span class="n">This</span> <span class="n">file</span> <span class="n">is</span> <span class="n">part</span> <span class="n">of</span> <span class="n">the</span> <span class="s">"Coroutine"</span> <span class="n">project</span> <span class="n">and</span> <span class="n">released</span> <span class="n">under</span> <span class="n">the</span> <span class="n">MIT</span> <span class="n">License</span><span class="p">.</span>
<span class="o">*</span>
</code></pre>
<p>The problem is, there is no definition of "the MIT License" throughout the entire project.</p>
<p><a class="user active user-mention" href="https://bugs.ruby-lang.org/users/3344">@ioquatix (Samuel Williams)</a> can you add your terms somewhere inside of LEGAL? There are several other materials also under the MIT license. You can follow how they are listed up.</p> Ruby master - Feature #16657 (Assigned): Don't ship bundled gems as .gem files as well as in expa...https://bugs.ruby-lang.org/issues/166572020-02-27T06:50:02Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>Working at <a class="issue tracker-1 status-5 priority-4 priority-default closed" title="Bug: Extensions Do Not Compile on Mingw64 with mingw32-make (Closed)" href="https://bugs.ruby-lang.org/issues/16651">#16651</a>, I wonder why the release tarball ships with the bundled gem in form of .gem packages as well as the expanded sources. It would be nice, if one option is chosen. Ideally just the .gem packages, because these are vanilla upstream packages installable via RubyGems without rbinstall magic.</p> Ruby master - Misc #16630 (Assigned): Deprecate pub/ruby/*snapshot* and use pub/ruby/snapshot/* i...https://bugs.ruby-lang.org/issues/166302020-02-13T08:51:43Zznz (Kazuhiro NISHIYAMA)
<p>In <a href="https://www.ruby-lang.org/en/downloads/" class="external">https://www.ruby-lang.org/en/downloads/</a>, snapshots links to <code>pub/ruby/snapshot.*</code> and <code>pub/ruby/stable-snapshot.*</code> as official snapshot tarballs now.</p>
<p>I want to change links to snapshot tarballs in <a href="https://cache.ruby-lang.org/pub/ruby/snapshot/" class="external">https://cache.ruby-lang.org/pub/ruby/snapshot/</a>.</p>
<p>They created by <a href="https://github.com/ruby/actions/" class="external">https://github.com/ruby/actions/</a> now.</p>
<p>Tarballs under <code>pub/ruby/snapshot/</code> have branch name (e.g. <code>ruby_2_7</code>) in filenames.<br>
And they are tested. (but they remain even if tests failed.)</p>
<p><code>pub/ruby/*snapshot.*</code> are not tested.<br>
And there are fewer files under <code>pub/ruby/</code> without sub-directory recently. (e.g. <code>ruby- 2.7.*</code> are in <code>pub/ruby/2.7/</code> only.)<br>
So I want to remove them.</p>
<p>Because of the plan, <code>stable-snapshot.*</code> are still snapshot of <code>ruby_2_6</code> instead of <code>ruby_2_7</code>.</p> Ruby master - Feature #16350 (Assigned): ArithmeticSequence#member? can result in infinite loophttps://bugs.ruby-lang.org/issues/163502019-11-16T17:20:32Zparker (Parker Finch)
<p>I'm not sure if this is a bug or a feature, it feels somewhere in between.</p>
<p>This is my first time contributing to the Ruby code, let me know what I can improve in this report!</p>
<p>ArithmeticSequence#member? enumerates through the sequence in order to determine if an element is included. (It just uses Enumerable#member?.) This leads to an infinite loop if the sequence is infinite and the element is not included, such as <code>1.step.member?(0)</code>.</p>
<p>I expected <code>1.step.member?(0)</code> to return <code>false</code>.</p>
<p>Since ArithmeticSequences are much more constrained than regular Enumerables, the #member? method can be overridden to efficiently determine if an element is included in the sequence.</p>
<p>I started implementing this change (patch attached) but got a little confused when trying to handle floats. Before digging in too deeply, I wanted to check if this is a change that will be accepted.</p>
<p>Let me know if I should keep looking into this!</p> Ruby master - Feature #16012 (Assigned): Add a (small) test-install suite?https://bugs.ruby-lang.org/issues/160122019-07-19T14:27:56ZMSP-Greg (Greg L)
<p>At various times there has been discussion about whether testing should require <code>make install</code>. Although I prefer to do testing using install (vs build), I see it as a choice, and not a requirement.</p>
<p>From time to time various issues have arisen that cannot be found with 'build' testing. Often, these issues cause CI test failure with master/trunk/ruby-head in external repos. Sometimes people blame 'Core', other times Travis, or rvm. Regardless, it doesn't look good.</p>
<p>So, might a small set of tests that check install functionality be added? It may need to be two separate (but equivalent) scripts. One for *nix, one for Windows.</p>
<p>In ruby-loco, I'm using a ps1 script to check that CLI bin files work. As soon as the update is pushed here, I'll add a test for nested bundler commands...</p> Ruby master - Feature #15939 (Assigned): Dump symbols reference to their fstr in ObjectSpace.dump()https://bugs.ruby-lang.org/issues/159392019-06-19T12:52:38Zbyroot (Jean Boussier)byroot@ruby-lang.org
<p>Patch: <a href="https://github.com/ruby/ruby/pull/2240" class="external">https://github.com/ruby/ruby/pull/2240</a></p>
<p>Symbols wether they are dynamic or static do hold a reference onto their respective fstring, so it's important to dump these references so that it's possible to see that a String isn't garbage collected because it has an associated Symbol.</p>
<p>Dumping a static Symbol (before):</p>
<pre><code>>> puts ObjectSpace.dump(:foobar)
{"type":"SYMBOL", "value":"foobar"}
</code></pre>
<p>after:</p>
<pre><code>>> puts ObjectSpace.dump(:foobar)
{"address":"0x7a210c", "type":"SYMBOL", "value":"foobar", "references":["0x7f8dd482c7d8"], "dynamic": false}
</code></pre>
<p>Dumping a dynamic Symbol (before):</p>
<pre><code>>> puts ObjectSpace.dump("foobar".to_sym)
{"address":"0x7fcdf7042eb0", "type":"SYMBOL", "class":"0x7fcdf70c8628", "frozen":true, "bytesize":6, "value":"foobar", "memsize":40, "flags":{"wb_protected":true}}
</code></pre>
<p>After:</p>
<pre><code>>> puts ObjectSpace.dump("foobar".to_sym)
{"address":"0x7fcdf7042eb0", "type":"SYMBOL", "class":"0x7fcdf70c8628", "frozen":true, "bytesize":6, "value":"foobar", "dynamic":true, "references":["0x7fcdf7042ed8"], "memsize":40, "flags":{"wb_protected":true}}
</code></pre>
<p>Limitations:</p>
<p><code>ObjectSpace.dump_all</code> rely on <code>rb_objspace_reachable_objects_from</code> to list an object's references.<br>
Because of this static symbol "references" are not followed, and as such are invisible in <code>ObjectSpace.dump_all</code>.</p>
<p>I'd like to correct it but it's quite more complicated because <code>rb_objspace_reachable_objects_from</code> is used by the GC, so I'd need to duplicate that function for <code>objspace_dump</code> usage.</p>
<p>So I wouldn't mind some opinion on that before attempting it.</p> Ruby master - Misc #15806 (Assigned): Explicitly initialise encodings on init to remove branches ...https://bugs.ruby-lang.org/issues/158062019-04-27T23:41:34Zmethodmissing (Lourens Naudé)lourens@bearmetal.eu
<p>References Github PR <a href="https://github.com/ruby/ruby/pull/2128" class="external">https://github.com/ruby/ruby/pull/2128</a></p>
<p>I noticed that the encoding table is loaded on startup of even just <code>miniruby</code> (minimal viable interpreter use case) through this backtrace during ruby setup:</p>
<pre><code>/home/lourens/src/ruby/ruby/miniruby(rb_enc_init+0x12) [0x56197b0c0c72] encoding.c:587
/home/lourens/src/ruby/ruby/miniruby(rb_usascii_encoding+0x1a) [0x56197b0c948a] encoding.c:1357
/home/lourens/src/ruby/ruby/miniruby(Init_sym+0x7a) [0x56197b24810a] symbol.c:42
/home/lourens/src/ruby/ruby/miniruby(rb_call_inits+0x1d) [0x56197b11afed] inits.c:25
/home/lourens/src/ruby/ruby/miniruby(ruby_setup+0xf6) [0x56197b0ec9d6] eval.c:74
/home/lourens/src/ruby/ruby/miniruby(ruby_init+0x9) [0x56197b0eca39] eval.c:91
/home/lourens/src/ruby/ruby/miniruby(main+0x5a) [0x56197b051a2a] ./main.c:41
</code></pre>
<p>Therefore I think it makes sense to instead initialize encodings explicitly just prior to symbol init, which is the first entry point into the interpreter loading that currently triggers <code>rb_enc_init</code> and remove the initialization check branches from the various lookup methods.</p>
<p>Some of the branches collapsed, <code>cachegrind</code> output, columns are <code>Ir Bc Bcm Bi Bim</code> with <code>Ir</code> (instructions retired), <code>Bc</code> (branches taken) and <code>Bcm</code> (branches missed) relevant here as there are no indirect branches (function pointers etc.):</p>
<p>(hot function, many instructions retired and branches taken and missed)</p>
<pre><code> . . . . . rb_encoding *
. . . . . rb_enc_from_index(int index)
835,669 0 0 0 0 {
13,133,536 6,337,652 50,267 0 0 if (!enc_table.list) {
3 0 0 0 0 rb_enc_init();
. . . . . }
23,499,349 8,006,202 293,161 0 0 if (index < 0 || enc_table.count <= (index &= ENC_INDEX_MASK)) {
. . . . . return 0;
. . . . . }
30,024,494 0 0 0 0 return enc_table.list[index].enc;
1,671,338 0 0 0 0 }
</code></pre>
<p>(cold function, representative of the utf8 variant more or less too)</p>
<pre><code> . . . . . rb_encoding *
. . . . . rb_ascii8bit_encoding(void)
. . . . . {
27,702 9,235 955 0 0 if (!enc_table.list) {
. . . . . rb_enc_init();
. . . . . }
9,238 0 0 0 0 return enc_table.list[ENCINDEX_ASCII].enc;
9,232 0 0 0 0 }
</code></pre>
<p>I think lazy loading encodings and populating the table is fine, but initializing it can be done more explicitly in the boot process.</p> Ruby master - Bug #15499 (Assigned): Breaking behavior on ruby 2.6: rb_thread_call_without_gvl do...https://bugs.ruby-lang.org/issues/154992019-01-03T01:37:49Zapolcyn (alex polcyn)
<p>This issue was noticed when trying to add ruby 2.6 support to the "grpc" ruby gem (this gem is a native C-extension), and was caught by a unit test.</p>
<p>There are several APIs on the grpc ruby gem (<a href="https://github.com/grpc/grpc/tree/master/src/ruby" class="external">https://github.com/grpc/grpc/tree/master/src/ruby</a>) that invoke "rb_thread_call_without_gvl" on the current thread, doing a blocking operation in the "without gvl" callback and cancel that blocking operation in the "unblocking function". These APIs work in ruby versions prior to ruby 2.6 (e.g. ruby 2.5), but have problems when used on ruby 2.6</p>
<p>Minimal repro:</p>
<p>My system:</p>
<pre><code>> lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 9.6 (stretch)
Release: 9.6
Codename: stretch
> ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547) [x86_64-linux
# I installed ruby 2.6.0 with rvm - https://rvm.io/rvm/install
> GRPC_CONFIG=dbg gem install grpc --platform ruby # build grpc gem from source with debug symbols
</code></pre>
<p>ruby script, "repro.rb" that looks like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'grpc'</span>
<span class="n">ch</span> <span class="o">=</span> <span class="no">GRPC</span><span class="o">::</span><span class="no">Core</span><span class="o">::</span><span class="no">Channel</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'localhost:1234'</span><span class="p">,</span> <span class="p">{},</span> <span class="ss">:this_channel_is_insecure</span><span class="p">)</span>
<span class="n">ch</span><span class="p">.</span><span class="nf">watch_connectivity_state</span><span class="p">(</span><span class="n">ch</span><span class="p">.</span><span class="nf">connectivity_state</span><span class="p">,</span> <span class="no">Time</span><span class="p">.</span><span class="nf">now</span> <span class="o">+</span> <span class="mi">360</span><span class="p">)</span>
</code></pre>
<p>Run "ruby repro.rb" with an interactive shell, and it will hang there. At this point, ctrl^C the process, and it will not terminate.<br>
What should happen is this unblocking func should be invoked: <a href="https://github.com/grpc/grpc/blob/master/src/ruby/ext/grpc/rb_channel.c#L354" class="external">https://github.com/grpc/grpc/blob/master/src/ruby/ext/grpc/rb_channel.c#L354</a>, but as seen with logging or debuggers, that unblocking func is never ran. Thus the blocking operation never completes and the main thread is stuck.</p>
<p>When the same repro.rb is ran on e.g. ruby 2.5.3 or ruby 2.4.1, the blocking operation is unblocked and the process terminates, as expected, when sending it a SIGINT.</p>
<p>Also note that if the blocking operation is put in a background thread, e.g. with this script:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require</span> <span class="s1">'grpc'</span>
<span class="n">th</span> <span class="o">=</span> <span class="no">Thread</span><span class="p">.</span><span class="nf">new</span> <span class="k">do</span>
<span class="n">ch</span> <span class="o">=</span> <span class="no">GRPC</span><span class="o">::</span><span class="no">Core</span><span class="o">::</span><span class="no">Channel</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'localhost:1234'</span><span class="p">,</span> <span class="p">{},</span> <span class="ss">:this_channel_is_insecure</span><span class="p">)</span>
<span class="n">ch</span><span class="p">.</span><span class="nf">watch_connectivity_state</span><span class="p">(</span><span class="n">ch</span><span class="p">.</span><span class="nf">connectivity_state</span><span class="p">,</span> <span class="no">Time</span><span class="p">.</span><span class="nf">now</span> <span class="o">+</span> <span class="mi">360</span><span class="p">)</span>
<span class="k">end</span>
<span class="n">th</span><span class="p">.</span><span class="nf">join</span>
</code></pre>
<p>then "unblocking" functions will in fact be invoked upon sending the process a SIGINT, so this looks like a problem specifically with rb_thread_call_without_gvl being used on the main thread.</p>
<p>Please let me know and I can provide more details or alternative repro cases.</p>
<p>Thanks in advance.</p> Ruby master - Misc #15487 (Assigned): Clarify default gems maintanance policyhttps://bugs.ruby-lang.org/issues/154872018-12-29T12:30:23Zzverok (Victor Shepelev)zverok.offline@gmail.com
<p>In addition to <a class="issue tracker-5 status-7 priority-4 priority-default closed" title="Misc: Default gems README.md (Feedback)" href="https://bugs.ruby-lang.org/issues/15486">#15486</a>, I'd like to raise the question of the general <em>maintanance policy</em> for "default" Ruby gems, in particular:</p>
<ul>
<li>who is responsible for each gem and how they should be contacted?</li>
<li>what are goals and policies for gems code quality and documentation?</li>
<li>where do default gems are discussed?</li>
<li>what are some promises/guarantees default gems maintainers try to fulfill?</li>
</ul>
<p>The most demonstrative example I'd like to point is <code>json</code> gem:</p>
<ul>
<li>The source at <a href="https://github.com/ruby/json" class="external">ruby/json</a> is NOT authoritative as far as I can tell, the authoritative one is <a href="https://github.com/flori/json" class="external">flori/json</a>
</li>
<li>The gem still holds signs of the times it was independent (<code>Pure</code> and <code>Ext</code> JSON implementations, but <code>Pure</code> is not copied into the <code>ruby/lib</code> on releases, rendering standard docs pretty weird), and has NO mention it is THE json gem of Ruby</li>
<li>The gem seems unmaintained, considering the amount of <a href="https://github.com/flori/json/pulls" class="external">PRs</a> and <a href="https://github.com/flori/json/issues" class="external">issues</a>, lot of them without any reaction for months</li>
<li>When I tried to update JSON docs, in <a href="https://bugs.ruby-lang.org/issues/14581" class="external">core tracker issue</a> I was asked to make a PR to "upstream repository", but there, the PRs (<a href="https://github.com/flori/json/pull/347" class="external">#347</a>, <a href="https://github.com/flori/json/pull/349" class="external">#349</a>) was simply ignored; Ruby 2.6 was released without new docs, despite the fact PRs were made at <strong>March</strong> and require almost no code review (unlike even some promising optimization PRs, that were also hanging there since Feb/Mar)</li>
</ul>
<p>It is just one unfortunate case (TBH, my experience with contributing to other libraries, like <code>csv</code> and <code>psych</code> was much smoother), but it demonstrates some common lack of transparency in maintaining of Ruby's standard library</p> Ruby master - Feature #15166 (Assigned): 2.5 times faster implementation than current gcd implmen...https://bugs.ruby-lang.org/issues/151662018-09-26T18:30:29Zjzakiya (Jabari Zakiya)
<p>This is to be more explicit (and accurate) than <a href="https://bugs.ruby-lang.org/issues/15161" class="external">https://bugs.ruby-lang.org/issues/15161</a></p>
<p>This is my modified gcd benchmarks code, originally presented by Daniel Lemire (see 15161).</p>
<p><a href="https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566" class="external">https://gist.github.com/jzakiya/44eae4feeda8f6b048e19ff41a0c6566</a></p>
<p>Ruby's current implementation of Stein's gcd algorithm is only slightly faster than the<br>
code posted on the wikepedia page, and over 2.5 times slower than the fastest implementation<br>
in the benchmarks.</p>
<pre><code>[jzakiya@localhost ~]$ ./gcdbenchmarks
gcd between numbers in [1 and 2000]
gcdwikipedia7fast32 : time = 99
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 139
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 267
gcdwikipedia2 : time = 321
gcd between numbers in [1000000001 and 1000002000]
gcdwikipedia7fast32 : time = 100
gcdwikipedia4fast : time = 121
gcdFranke : time = 126
gcdwikipedia3fast : time = 134
gcdwikipedia2fastswap : time = 136
gcdwikipedia5fast : time = 138
gcdwikipedia7fast : time = 138
gcdwikipedia2fast : time = 136
gcdwikipedia6fastxchg : time = 144
gcdwikipedia2fastxchg : time = 156
gcd_iterative_mod : time = 210
gcd_recursive : time = 215
basicgcd : time = 211
rubygcd : time = 269
gcdwikipedia2 : time = 323
</code></pre>
<p>This is Ruby's code per: <a href="https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307" class="external">https://github.com/ruby/ruby/blob/3abbaab1a7a97d18f481164c7dc48749b86d7f39/rational.c#L285-L307</a><br>
which is basically the wikepedia implementation.</p>
<pre><code>inline static long
i_gcd(long x, long y)
{
unsigned long u, v, t;
int shift;
if (x < 0)
x = -x;
if (y < 0)
y = -y;
if (x == 0)
return y;
if (y == 0)
return x;
u = (unsigned long)x;
v = (unsigned long)y;
for (shift = 0; ((u | v) & 1) == 0; ++shift) {
u >>= 1;
v >>= 1;
}
while ((u & 1) == 0)
u >>= 1;
do {
while ((v & 1) == 0)
v >>= 1;
if (u > v) {
t = v;
v = u;
u = t;
}
v = v - u;
} while (v != 0);
return (long)(u << shift);
}
</code></pre>
<p>This is the fastest implementation from the benchmarks. (I originally, wrongly, cited<br>
the implementation in the article, which is 4|5th fastest in benchmarks, but<br>
still almost 2x faster than the Ruby implementation.)</p>
<pre><code>// based on wikipedia's article,
// fixed by D. Lemire, K. Willets
unsigned int gcdwikipedia7fast32(unsigned int u, unsigned int v)
{
int shift, uz, vz;
if ( u == 0) return v;
if ( v == 0) return u;
uz = __builtin_ctz(u);
vz = __builtin_ctz(v);
shift = uz > vz ? vz : uz;
u >>= uz;
do {
v >>= vz;
int diff = v;
diff -= u;
if ( diff == 0 ) break;
vz = __builtin_ctz(diff);
if ( v < u ) u = v;
v = abs(diff);
} while( 1 );
return u << shift;
}
</code></pre>
<p>The key to speeding up all the algorithms is using the <code>__builtin_ctz(x)</code> directive<br>
to determine the number of trailing binary '0's.</p> Ruby master - Misc #14917 (Assigned): Add RDoc documents to tar ballhttps://bugs.ruby-lang.org/issues/149172018-07-18T04:08:50Zaycabta (aycabta .)aycabta@gmail.com
<p>I guess that distribution packages should include RDoc documents' files because RDoc documents installation step needs too long time.</p>
<p>There is the other reason. RDoc sometimes fails during "generating RDoc documentation" phase of installation.</p>
<p>Some case examples:</p>
<ul>
<li><a href="https://bugs.ruby-lang.org/issues/11494" class="external">https://bugs.ruby-lang.org/issues/11494</a></li>
<li><a href="https://bugs.ruby-lang.org/issues/14663" class="external">https://bugs.ruby-lang.org/issues/14663</a></li>
<li><a href="https://bugs.ruby-lang.org/issues/14874" class="external">https://bugs.ruby-lang.org/issues/14874</a></li>
<li><a href="https://bugs.ruby-lang.org/issues/11514" class="external">https://bugs.ruby-lang.org/issues/11514</a></li>
</ul>
<p>Maybe, generating RDoc documentation is so heavy task for low memory situation, and other tasks are lighter than it.</p> Ruby master - Feature #14476 (Assigned): Adding same_all? for checking whether all items in an Ar...https://bugs.ruby-lang.org/issues/144762018-02-14T15:41:30Zmrkn (Kenta Murata)muraken@gmail.com
<p>In this issue, I propose to introduce <code>same_all?</code> instance method of <code>Array</code> class. This new method checks whether all items in the receiver are the same.</p>
<p>Today, I needed to write a code to judge whether all items in an <code>Array</code> are the same. I wanted to make the following expression, which I've written first, more efficient.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span> <span class="p">}</span>
</code></pre>
<p>I considered about the following simpler case, too.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">ary</span><span class="p">.</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="p">}</span>
</code></pre>
<p>As I discussed with some CRuby committers and my colleagues at Speee, Inc., I found that both cases can be written more efficiently as follows:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># for the 1st case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nf">foo</span><span class="p">.</span><span class="nf">yield_self</span> <span class="p">{</span><span class="o">|</span><span class="n">e0</span><span class="o">|</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">].</span><span class="nf">all?</span> <span class="p">{</span><span class="o">|</span><span class="n">e</span><span class="o">|</span> <span class="n">e</span><span class="p">.</span><span class="nf">foo</span> <span class="o">==</span> <span class="n">e0</span> <span class="p">}</span> <span class="p">}</span><span class="err"> </span>
<span class="c1"># for the 2nd case</span>
<span class="n">ary</span><span class="p">.</span><span class="nf">empty?</span> <span class="o">||</span> <span class="n">ary</span><span class="p">[</span><span class="mi">0</span><span class="o">..-</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="n">ary</span><span class="p">[</span><span class="mi">1</span><span class="o">..-</span><span class="mi">1</span><span class="p">]</span>
</code></pre>
<p>However, it is not easy to understand the intent of either expression, which is to check whether all items are the same.</p>
<p>I want to give this feature a clear name to make code readable. And I think it should be provided as a core feature because it can be made more efficient by being implemented in C language.</p>
<p>The benchmark script is: <a href="https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5" class="external">https://gist.github.com/mrkn/26a0fcfc431a45fe809fbbef95aceaf5</a><br>
I used it to find the efficient expressions. The example result of this benchmark on my MacBook Pro is here.</p>
<pre><code>$ ruby -v bench.rb
ruby 2.6.0dev (2018-02-14 trunk 62402) [x86_64-darwin16]
----------------------------------------
Benchmark case: shuffle
user system total real
all?-method-1 0.001525 0.000088 0.001613 ( 0.001632)
all?-method-2 0.000489 0.000031 0.000520 ( 0.000565)
all?-method-3 0.000444 0.000039 0.000483 ( 0.000482)
all?-item 0.000325 0.000078 0.000403 ( 0.000402)
opt-method 0.655959 0.033814 0.689773 ( 0.708515)
opt-item 0.000316 0.000001 0.000317 ( 0.000317)
----------------------------------------
Benchmark case: tail0
user system total real
all?-method-1 9.412810 0.231126 9.643936 ( 9.681118)
all?-method-2 5.375075 0.137908 5.512983 ( 5.754550)
all?-method-3 5.226132 0.167640 5.393772 ( 5.507031)
all?-item 0.873700 0.007545 0.881245 ( 0.917210)
opt-method 5.319648 0.172547 5.492195 ( 5.633140)
opt-item 0.174349 0.001974 0.176323 ( 0.183002)
----------------------------------------
Benchmark case: head0
user system total real
all?-method-1 0.002421 0.000068 0.002489 ( 0.002489)
all?-method-2 0.002169 0.000213 0.002382 ( 0.002382)
all?-method-3 0.001624 0.000026 0.001650 ( 0.001651)
all?-item 0.000623 0.000001 0.000624 ( 0.000624)
opt-method 4.779120 0.146312 4.925432 ( 4.951167)
opt-item 0.000629 0.000001 0.000630 ( 0.000629)
----------------------------------------
Benchmark case: all1
user system total real
all?-method-1 9.379650 0.255865 9.635515 ( 9.683078)
all?-method-2 4.950280 0.150659 5.100939 ( 5.140174)
all?-method-3 4.857898 0.129125 4.987023 ( 5.003142)
all?-item 0.694113 0.001295 0.695408 ( 0.702370)
opt-method 5.032373 0.121708 5.154081 ( 5.189599)
opt-item 0.170540 0.002069 0.172609 ( 0.180343)
</code></pre> Ruby master - Feature #14412 (Assigned): DRb UNIX on local machine: add support for getpeereid()https://bugs.ruby-lang.org/issues/144122018-01-27T17:26:32ZAnonymous
<p>Hi,</p>
<p><code>UNIXSocket</code> has this method <code>#getpeereid()</code> which returns effective user ID and effective group ID.</p>
<p>DRb using <code>drbunix://</code> on local machine doesn't support that method. In my use case, I need to verify clients via that method. So it would be great if you add support to DRb.</p>
<p>Actually that method <code>#getpeereid()</code> is from <code>BaseSocket</code>, but documentation states that it only supports UNIX sockets. I mean, it's a general method from parent class. So you can do the same with DRb: add some similar method, but only works via <code>drbunix://</code> on local machine. Otherwise you can raise error...</p>
<p>Thank you,</p> Ruby master - Bug #13999 (Assigned): Cygwin 環境で ripper_state_lex.rb がコアダンプするhttps://bugs.ruby-lang.org/issues/139992017-10-11T05:19:02Zhigaki (masaru higaki)mas.higa@gmail.com
<p>いくつかの gem をインストールした際にコアダンプしました。</p>
<p>--no-ri を付けるとコアダンプしないことから ri の何かが関係していそうです。</p>
<p>$ gem install bitclust-core # コアダンプ<br>
$ gem install --no-ri bitclust-core # コアダンプしない</p>
<p>標準出力、エラー出力を添付します。</p> Ruby master - Feature #13821 (Assigned): Allow fibers to be resumed across threadshttps://bugs.ruby-lang.org/issues/138212017-08-16T17:19:49Zcremes (Chuck Remes)
<p>Given a Fiber created in ThreadA, Ruby 2.4.1 (and earlier releases) raise a FiberError if the fiber is resumed in ThreadB or any other thread other than the one that created the original Fiber.</p>
<p>Sample code attached to demonstrate problem.</p>
<p>If Fibers are truly encapsulating all of the data for the continuation, we should be allowed to move them between Threads and resume their operation.</p>
<p>Why?</p>
<p>One use-case is to support the async-await asynchronous programming model. In that model, a method marked async runs <em>synchronously</em> until the #await method is encountered. At that point the method is suspended and control is returned to the caller. When the #await method completes (asynchronously) then it may resume the suspended method and continue. The only way to capture this program state, suspend and resume, is via a Fiber.</p>
<p>example:</p>
<pre><code>class Wait
include AsyncAwait
def dofirst
async do
puts 'Synchronously print dofirst.'
result = await { dosecond }
puts 'dosecond is complete'
result
end
end
def dosecond
async do
puts 'Synchronously print dosecond from async task.'
slept = await { sleep 3 }
puts 'Sleep complete'
slept
end
end
def run
task = dofirst
puts 'Received task'
p AsyncAwait::Task.await(task)
end
end
Wait.new.run
</code></pre>
<pre><code># Expected output:
# Synchronous print dofirst.
# Received task
# Synchronously print dosecond from async task.
# Sleep complete
# dosecond is complete
# 3
</code></pre>
<p>Right now the best way to accomplish suspension of the #dofirst and #dosecond commands and allow them to run asynchronously is by passing those blocks to <em>another thread</em> (other than the callers thread) so they can be encapsulated in a new Fiber and then yielded. When it's time to resume after #await completes, that other thread must lookup the fiber and resume it. This is lots of extra code and logic to make sure that fibers are only resumed on the threads that created them. Allowing Fibers to migrate between threads would eliminate this problem.</p> Ruby master - Misc #13622 (Assigned): Documentation missinghttps://bugs.ruby-lang.org/issues/136222017-06-02T14:08:27Zsergzhum (Sergey Zhumatiy)
<p>In documentation for method IO.nread important information is missing: you must do 'require "io/wait"' before using it. May be some other methods of IO in 'io/wait' are missed this IMPORTANT notice.</p> Ruby master - Feature #13604 (Assigned): Exposing alternative interface of readlinehttps://bugs.ruby-lang.org/issues/136042017-05-27T10:01:41Zgraywolf (Gray Wolf)
<p>GNU Readline has multiple modes of operation. At the moment, the readline extension only supports typical, <code>Readline.readline</code> mode. However, there is also alternative callback-based interface which is also useful.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">require_relative</span> <span class="s1">'readline'</span>
<span class="no">PROMPT</span> <span class="o">=</span> <span class="s2">"rltest$ "</span>
<span class="vg">$running</span> <span class="o">=</span> <span class="kp">true</span>
<span class="vg">$sigwinch_received</span> <span class="o">=</span> <span class="kp">false</span>
<span class="no">Readline</span><span class="p">.</span><span class="nf">handler_install</span><span class="p">(</span><span class="no">PROMPT</span><span class="p">,</span> <span class="ss">add_hist: </span><span class="kp">true</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span>
<span class="c1"># Can use ^D (stty eof) or `exit' to exit.</span>
<span class="k">if</span> <span class="o">!</span><span class="n">line</span> <span class="o">||</span> <span class="n">line</span> <span class="o">==</span> <span class="s2">"exit"</span>
<span class="nb">puts</span> <span class="k">unless</span> <span class="n">line</span>
<span class="nb">puts</span> <span class="s2">"exit"</span>
<span class="no">Readline</span><span class="p">.</span><span class="nf">handler_remove</span>
<span class="vg">$running</span> <span class="o">=</span> <span class="kp">false</span>
<span class="k">else</span>
<span class="nb">puts</span> <span class="s2">"input line: </span><span class="si">#{</span><span class="n">line</span><span class="si">}</span><span class="s2">"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="no">Signal</span><span class="p">.</span><span class="nf">trap</span><span class="p">(</span><span class="s1">'SIGWINCH'</span><span class="p">)</span> <span class="p">{</span> <span class="vg">$sigwinch_received</span> <span class="o">=</span> <span class="kp">true</span> <span class="p">}</span>
<span class="k">while</span> <span class="vg">$running</span> <span class="k">do</span>
<span class="n">rs</span> <span class="o">=</span> <span class="no">IO</span><span class="p">.</span><span class="nf">select</span><span class="p">([</span><span class="vg">$stdin</span><span class="p">])</span>
<span class="k">if</span> <span class="vg">$sigwinch_received</span>
<span class="no">Readline</span><span class="p">.</span><span class="nf">resize_terminal</span>
<span class="vg">$sigwinch_received</span> <span class="o">=</span> <span class="kp">false</span>
<span class="k">end</span>
<span class="no">Readline</span><span class="p">.</span><span class="nf">read_char</span> <span class="k">if</span> <span class="n">r</span> <span class="o">=</span> <span class="n">rs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">end</span>
<span class="nb">puts</span> <span class="s2">"rltest: Event loop has exited"</span>
</code></pre>
<p>Patch adding support for this is attached. This is my first try at contributing to ruby, so please tell me what I did wrong (I'm sure something, C is not my strong language).</p> Ruby master - Feature #13577 (Assigned): Digest.file accidentally receives File object but uses f...https://bugs.ruby-lang.org/issues/135772017-05-19T09:03:19Znaruse (Yui NARUSE)naruse@airemix.jp
<p>Digest::SHA256.file()'s first argument is file path name but it accidentally accepts file object.<br>
But for file objects created with O_TMPFILE to_path returns the directory of the temporary file and this File.open will fail.</p>
<pre><code> class ::Digest::Class
# Creates a digest object and reads a given file, _name_.
# Optional arguments are passed to the constructor of the digest
# class.
#
# p Digest::SHA256.file("X11R6.8.2-src.tar.bz2").hexdigest
# # => "f02e3c85572dc9ad7cb77c2a638e3be24cc1b5bea9fdbb0b0299c9668475c534"
def self.file(name, *args)
new(*args).file(name)
end
end
module Instance
# Updates the digest with the contents of a given file _name_ and
# returns self.
def file(name)
File.open(name, "rb") {|f|
buf = ""
while f.read(16384, buf)
update buf
end
}
self
end
</code></pre> Ruby master - Feature #13388 (Assigned): gc.c: Add GC.get_parameters and .set_parametershttps://bugs.ruby-lang.org/issues/133882017-03-29T10:03:24Zmakimoto (Shimpei Makimoto)s@makimoto.org
<p>These methods are for inspecting and modifying MRI's GC parameters. It may be<br>
useful for realtime parameter tuning with GC.stat, user requests and so on.</p>
<p>This work is done by Tomohiro Moro (@slightair) and me (<a class="user active user-mention" href="https://bugs.ruby-lang.org/users/6929">@makimoto (Shimpei Makimoto)</a>).</p>
<p>GH issue: <a href="https://github.com/ruby/ruby/pull/1572" class="external">https://github.com/ruby/ruby/pull/1572</a></p>
<p>We're trying this patch with our environments and report here.</p> Ruby master - Feature #13252 (Assigned): C API for creating strings without copyinghttps://bugs.ruby-lang.org/issues/132522017-02-25T00:19:15Ztenderlovemaking (Aaron Patterson)tenderlove@ruby-lang.org
<p>Hi,</p>
<p>I'd like to have a C API that allows me to create String objects without copying the underlying <code>char *</code>. Basically a C API similar to the <code>rb_str_new_static</code>, but have the GC free the underlying <code>char *</code> when the object dies. The use case is that at work we have C libraries that allocate <code>char *</code> and we want to pass those to Ruby land without copying the buffer. Here is an example of what we're doing now:</p>
<p><a href="https://github.com/arthurnn/memcached/commit/1886546944b420dc6953096ba1f5eae772001e31#diff-f508f9b8263ea397534b2b3f8efed987R147" class="external">https://github.com/arthurnn/memcached/commit/1886546944b420dc6953096ba1f5eae772001e31#diff-f508f9b8263ea397534b2b3f8efed987R147</a></p>
<p>I'd like it if there was a public API for doing something like this.</p>
<p>Thank you!</p>
<p>P.S. I am sure I can't be the first to ask for this, but I couldn't find a similar issue in RedMine, so if this has been answered I apologize.<br>
P.P.S. I've added a patch for kind of what I want.</p> Ruby master - Feature #12656 (Assigned): Expand short paths with File.expand_pathhttps://bugs.ruby-lang.org/issues/126562016-08-04T20:06:47Zdavispuh (Dāvis Mosāns)
<p>Currently File.expand_path expands short path only if it's last part.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">puts</span> <span class="no">File</span><span class="p">.</span><span class="nf">expand_path</span><span class="p">(</span><span class="s1">'C:/VERYLO~1'</span><span class="p">)</span>
<span class="nb">puts</span> <span class="no">File</span><span class="p">.</span><span class="nf">expand_path</span><span class="p">(</span><span class="s1">'C:/VERYLO~1/OTHERL~1'</span><span class="p">)</span>
</code></pre>
<p>Produces</p>
<pre><code>C:/VeryLongName12345
C:/VERYLO~1/OtherLongName54321
</code></pre>
<p>With attached patch it will always be long path</p>
<pre><code>C:/VeryLongName12345
C:/VeryLongName12345/OtherLongName54321
</code></pre>
<p>This also fixes TestDir#test_glob test because it was failing due short path.</p> Ruby master - Feature #12543 (Assigned): explicit tail call syntax: foo() then returnhttps://bugs.ruby-lang.org/issues/125432016-07-02T17:24:19Zmame (Yusuke Endoh)mame@ruby-lang.org
<p>How about introducing a new syntax for tail call?</p>
<pre><code>def foo()
foo()
end
foo() #=> stack level too deep
</code></pre>
<pre><code>def bar()
bar() then return
end
bar() #=> infinite loop
</code></pre>
<ul>
<li>no new keyword (cf. <code>goto foo()</code>)</li>
<li>no conflict with any existing syntax</li>
<li>an experimental patch is available (attached)</li>
<li>no shift/reduce nor reduce/reduce conflict in parse.y</li>
</ul>
<p>--<br>
Yusuke Endoh <a href="mailto:mame@ruby-lang.org" class="email">mame@ruby-lang.org</a></p> Ruby master - Feature #12281 (Assigned): Allow lexically scoped use of refinements with `using {}...https://bugs.ruby-lang.org/issues/122812016-04-14T03:48:01Zdanielpclark (Daniel P. Clark)6ftdan@gmail.com
<p>In Ruby 2.2.3 a refinement could be used in a begin/end block.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">module</span> <span class="nn">Moo</span>
<span class="n">refine</span> <span class="no">Fixnum</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">to_s</span>
<span class="s2">"moo"</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">begin</span> <span class="c1"># valid Ruby 2.2.3 and NOT Ruby 2.3</span>
<span class="n">using</span> <span class="no">Moo</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">to_s</span>
<span class="k">end</span>
<span class="c1"># => "moo"</span>
</code></pre>
<p>Since this use case has been removed I would like to propose an alternative.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">using</span> <span class="no">Moo</span> <span class="k">do</span>
<span class="mi">1</span><span class="p">.</span><span class="nf">to_s</span>
<span class="k">end</span>
<span class="c1"># => "moo"</span>
</code></pre>
<p>I would like to propose allowing refinements to take a block and perform the refinement within the block and work just as if it were in it's own lexically scoped class.</p>
<p>I've been writing a lot of Rust lately and have found that their way of implementing Traits is just like Ruby's refinements except for that you can use Rust's version of refinements anywhere. Since Ruby's implementation is strictly lexically scoped I merely suggest a block syntax for <code>using</code> to allow greater expansion of refinements.</p>
<pre><code class="rust syntaxhl" data-language="rust"><span class="c1">// Rust</span>
<span class="k">impl</span> <span class="n">MyCapitalize</span> <span class="k">for</span> <span class="nb">String</span> <span class="p">{</span>
<span class="k">fn</span> <span class="nf">my_capitalize</span><span class="p">(</span><span class="o">&</span><span class="k">self</span><span class="p">)</span> <span class="k">-></span> <span class="k">Self</span> <span class="p">{</span>
<span class="c1">// code here</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">use</span> <span class="n">MyCapitalize</span><span class="p">;</span>
<span class="nn">String</span><span class="p">::</span><span class="nf">from</span><span class="p">(</span><span class="s">"hello"</span><span class="p">)</span><span class="nf">.my_capitalize</span><span class="p">()</span>
</code></pre>
<p>Rust lets you use the "refinement" of the trait implementation anywhere you use <code>use</code> just like Ruby's <code>using</code>. But currently Ruby restricts where <code>using</code> can be used. I would like that restriction to be lifted by allowing <code>using</code> to take a block.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># Ruby</span>
<span class="k">module</span> <span class="nn">MyCapitalize</span>
<span class="n">refine</span> <span class="no">String</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">my_capitalize</span>
<span class="c1"># code here</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">using</span> <span class="no">MyCapitalize</span> <span class="k">do</span>
<span class="s2">"hello"</span><span class="p">.</span><span class="nf">my_capitalize</span>
<span class="k">end</span>
<span class="c1"># => "Hello"</span>
</code></pre>
<p>This way we keep Ruby's strict lexical scope behavior and at the same time allow refinement usage anywhere we need it.</p> Ruby master - Feature #12020 (Assigned): Documenting Ruby memory modelhttps://bugs.ruby-lang.org/issues/120202016-01-25T19:20:30Zpitr.ch (Petr Chalupa)
<p>Defining a memory model for a language is necessary to be able to reason about a program behavior in a concurrent or parallel environment.</p>
<p>There was a document created describing a Ruby memory model for concurrent-ruby gem, which fits several Ruby language implementations. It was necessary to be able to build lower-level unifying layer that enables creation of concurrency abstractions. They can be implemented only once against the layer, which ensures that it runs on all Ruby implementations.</p>
<p>The Ruby MRI implementation has stronger undocumented guaranties because of GIL semantics than the memory model, but the few relaxations from MRIs behavior allow other implementations to fit the model as well and to improve performance.</p>
<p>This issue proposes to document the Ruby memory model. The above mentioned memory model document which was created for concurrent-ruby can be used as a starting point: <a href="https://docs.google.com/document/d/1pVzU8w_QF44YzUCCab990Q_WZOdhpKolCIHaiXG-sPw/edit#" class="external">https://docs.google.com/document/d/1pVzU8w_QF44YzUCCab990Q_WZOdhpKolCIHaiXG-sPw/edit#</a>. Please comment in the document or here.</p>
<p>The aggregating issue of this effort can be found <a href="https://bugs.ruby-lang.org/issues/12019" class="external">here</a>.</p> Ruby master - Feature #11955 (Assigned): Expose Object that Receives logs in Loggerhttps://bugs.ruby-lang.org/issues/119552016-01-05T21:59:29Zschneems (Richard Schneeman)
<p>I need to be able to perform logic based on the destination of a current logger, this is currently not possible without <code>instance_variable_get</code>. Why would you need to see what destination a logger is going to? There is a common pattern in long lived programs like webservers. You want logs on disk for later reference, but you also want them in STDOUT to make development and debugging easier. Rails does this in development mode. Since there is no way to see if a logger is already going to STDOUT, it gets extended to log to STDOUT so logs show up twice.</p>
<p>While that example was complicated the logic I want is very simple: if you have a logger that is logging to STDOUT, do nothing, otherwise log to STDOUT and current logger. You cannot do this today without exposing the destination of the logger. This patch exposes the logger destination and allows us to write code like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">make_sure_logging_to_stdout</span><span class="p">(</span><span class="n">logger</span><span class="p">)</span>
<span class="k">unless</span> <span class="n">logger</span><span class="p">.</span><span class="nf">destination</span> <span class="o">==</span> <span class="no">STDOUT</span> <span class="c1"># <==== Cannot do this today</span>
<span class="n">stdout_logger</span> <span class="o">=</span> <span class="o">::</span><span class="no">Logger</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">STDOUT</span><span class="p">)</span>
<span class="n">logger</span><span class="p">.</span><span class="nf">extend</span><span class="p">(</span><span class="no">Module</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">((</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">stdout_logger</span><span class="p">.</span><span class="nf">add</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">super</span><span class="p">(</span><span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">logger</span> <span class="o">=</span> <span class="no">Logger</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="no">STDOUT</span><span class="p">)</span>
<span class="n">make_sure_logging_to_stdout</span><span class="p">(</span><span class="n">logger</span><span class="p">)</span>
<span class="n">logger</span><span class="p">.</span><span class="nf">fatal</span><span class="p">(</span><span class="s2">"An error has occured"</span><span class="p">)</span>
</code></pre>
<p>We should be able to inspect the destination of a logger, this patch enables this functionality.</p> Ruby master - Misc #10560 (Assigned): confusion between x=x+y, x+=y, x.concat(y) and y.each{|z| x...https://bugs.ruby-lang.org/issues/105602014-12-01T15:53:01Zmpapis (Michal Papis)mpapis@gmail.com
<p>while discussing a ticket I have noticed that there is no documentation for <code>+=</code></p>
<p>I was expecting <code>+=</code> to behave as <code>concat</code> but instead it behaves as <code>x=x+y</code> which for every operation clones the array and updates the variable with new value so it behaves similarly to <code>x=x.dup.concat(y)</code> and is slightly faster, but using plane <code>x.concat(y)</code> is a lot faster from both <code>each<<</code> and <code>+=</code></p>
<p>I would either like to get:</p>
<ul>
<li>updated docs that describe concept of <code>+=</code> and show the difference from <code>concat</code>
</li>
<li>or change <code>+=</code> to use <code>concat</code> which is faster - and add docs ;) (I would expect <code>+=</code> to use <code>concat</code> when available)</li>
</ul>
<p>here is a test:</p>
<pre><code>require 'benchmark'
rep = 10_000
Benchmark.bmbm do |x|
{
1..25 => [],
"a".."z" => "",
}.each do |base, storage|
base = base.to_a
basej = base
class_name = storage.class.to_s
x.report(class_name+'#concat') do
a = storage.dup
basej = base.join if storage == ""
rep.times { a.concat(basej) }
end
x.report(class_name+'#<<') do
a = storage.dup
basej = base.join if storage == ""
rep.times { base.each { |e| a << e } }
end
x.report(class_name+'#+=') do
a = storage.dup
basej = base.join if storage == ""
rep.times { a += basej }
end
x.report(class_name+'#dup.concat') do
a = storage.dup
basej = base.join if storage == ""
rep.times { a = a.dup.concat(basej) }
end
end
end
</code></pre>
<p>and here are results on my machine:</p>
<pre><code> user system total real
Array#concat 0.000000 0.000000 0.000000 ( 0.001422)
Array#<< 0.020000 0.000000 0.020000 ( 0.014356)
Array#+= 1.270000 0.230000 1.500000 ( 1.498558)
Array#dup.concat 2.720000 0.190000 2.910000 ( 2.915701)
String#concat 0.000000 0.000000 0.000000 ( 0.001072)
String#<< 0.030000 0.000000 0.030000 ( 0.025828)
String#+= 0.130000 0.010000 0.140000 ( 0.135143)
String#dup.concat 0.210000 0.020000 0.230000 ( 0.227470)
</code></pre> Ruby master - Feature #10481 (Assigned): Add "if" and "unless" clauses to rescue statementshttps://bugs.ruby-lang.org/issues/104812014-11-05T19:20:10Zjavawizard (Alex Boyd)alex@opengroove.org
<p>I'd like to propose a syntax change: allow boolean "if" and "unless" clauses to follow a rescue statement.</p>
<p>Consider the following:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span>
<span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">else</span>
<span class="k">raise</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>This is a fairly common way of dealing with exceptions where some condition above and beyond the exception's type determines whether the exception should be rescued. It's verbose, though, and it's not obvious at first glance exactly what conditions are being rescued, especially if "...handle error..." is more than a few lines long. I propose that the following be allowed:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>"unless" would, of course, be allowed as well:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">unless</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">2</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>A rescue statement whose boolean condition failed would be treated the same as if the exception being raised didn't match the exception being rescued, and move on to the next rescue statement:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">1</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span> <span class="n">code</span> <span class="mi">1</span><span class="o">...</span>
<span class="k">rescue</span> <span class="no">SomeError</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">error_code</span> <span class="o">==</span> <span class="mi">2</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span> <span class="n">code</span> <span class="mi">2</span><span class="o">...</span>
<span class="k">end</span>
</code></pre>
<p>And finally, catch-all rescue statements would be allowed as well:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">begin</span>
<span class="o">...</span>
<span class="k">rescue</span> <span class="o">=></span> <span class="n">e</span> <span class="k">if</span> <span class="n">e</span><span class="p">.</span><span class="nf">message</span> <span class="o">==</span> <span class="s2">"some error"</span>
<span class="o">...</span><span class="n">handle</span> <span class="n">error</span><span class="o">...</span>
<span class="k">end</span>
</code></pre> Ruby master - Feature #10038 (Assigned): Extend ObjectSpace.dump to expose buffer addresses for S...https://bugs.ruby-lang.org/issues/100382014-07-15T07:15:45Zko1 (Koichi Sasada)
<p>ObjectSpace.dump() expose internal information in JSON.<br>
How about to expose buffer addresses for String and Array?</p>
<pre><code class="diff syntaxhl" data-language="diff"><span class="gh">Index: ext/objspace/objspace_dump.c
===================================================================
</span><span class="gd">--- ext/objspace/objspace_dump.c (revision 46821)
</span><span class="gi">+++ ext/objspace/objspace_dump.c (working copy)
</span><span class="p">@@ -178,12 +178,16 @@</span> dump_object(VALUE obj, struct dump_confi
dump_append(dc, ", \"broken\":true");
if (FL_TEST(obj, RSTRING_FSTR))
dump_append(dc, ", \"fstring\":true");
<span class="gd">- if (STR_SHARED_P(obj))
</span><span class="gi">+
+ if (STR_SHARED_P(obj)) {
</span> dump_append(dc, ", \"shared\":true");
<span class="gi">+ }
</span> else {
dump_append(dc, ", \"bytesize\":%ld", RSTRING_LEN(obj));
<span class="gd">- if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj))
</span><span class="gi">+ if (!STR_EMBED_P(obj) && !STR_SHARED_P(obj) && (long)rb_str_capacity(obj) != RSTRING_LEN(obj)) {
</span> dump_append(dc, ", \"capacity\":%ld", rb_str_capacity(obj));
<span class="gi">+ dump_append(dc, ", \"ptr\":\"%p\"", RSTRING_PTR(obj));
+ }
</span>
if (is_ascii_string(obj)) {
dump_append(dc, ", \"value\":");
<span class="p">@@ -205,8 +209,14 @@</span> dump_object(VALUE obj, struct dump_confi
dump_append(dc, ", \"length\":%ld", RARRAY_LEN(obj));
if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, ELTS_SHARED))
dump_append(dc, ", \"shared\":true");
<span class="gd">- if (RARRAY_LEN(obj) > 0 && FL_TEST(obj, RARRAY_EMBED_FLAG))
</span><span class="gi">+ if (RARRAY_LEN(obj) > 0) {
+ if (FL_TEST(obj, RARRAY_EMBED_FLAG)) {
</span> dump_append(dc, ", \"embedded\":true");
<span class="gi">+ }
+ else {
+ dump_append(dc, ", \"ptr\":\"%p\"", RARRAY_PTR(obj));
+ }
+ }
</span> break;
case T_CLASS:
</code></pre>
<p>With this hack, we can know the real memory address of them and cooperate with other native tools.</p>
<p>BTW, ObjectSpace.dump() should support T_SYMBOL.</p> Ruby master - Feature #9235 (Assigned): Documentation for commercial supporthttps://bugs.ruby-lang.org/issues/92352013-12-10T05:36:24Zzzak (zzak _)
<p>We should document the following:</p>
<ul>
<li>What happens when a Ruby version goes EOL?</li>
<li>What can (my) company do to help maintain an EOL ruby?</li>
<li>How do we backport security patches?</li>
<li>How do we run tests?</li>
<li>How do we release our own version of ruby?</li>
</ul> Ruby master - Bug #9189 (Assigned): Build failure on Windows in case of nonascii TEMP environment.https://bugs.ruby-lang.org/issues/91892013-12-01T18:06:20Zphasis68 (Heesob Park)phasis@gmail.com
<p>I experienced a build failure during build extension library with trunk on Windows.</p>
<pre><code>make[2]: Entering directory `/c/work/ruby-2.1.0-r43936/ext/bigdecimal'
generating bigdecimal-i386-mingw32.def
compiling bigdecimal.c
In file included from bigdecimal.c:20:0:
bigdecimal.h:62:1: error: static declaration of 'labs' follows non-static declar
ation
make[2]: *** [bigdecimal.o] Error 1
make[2]: Leaving directory `/c/work/ruby-2.1.0-r43936/ext/bigdecimal'
make[1]: *** [ext/bigdecimal/all] Error 2
make[1]: Leaving directory `/c/work/ruby-2.1.0-r43936'
make: *** [build-ext] Error 2
</code></pre>
<p>I found the cause of this error is mkmk failure.<br>
Here is a part of mkmf.log</p>
<pre><code>have_func: checking for labs() in stdlib.h... -------------------- no
"i686-w64-mingw32-gcc -o conftest.exe -I../../.ext/include/i386-mingw32 -I../.././include -I../.././ext/bigdecimal -D_WIN32_WINNT=0x0501 -D_FILE_OFFSET_BITS=64 -O3 -fno-omit-frame-pointer -fno-fast-math -ggdb3 -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Wpointer-arith -Wwrite-strings -Wdeclaration-after-statement -Wimplicit-function-declaration conftest.c -L. -L../.. -L. -lmsvcrt-ruby210-static -lshell32 -lws2_32 -liphlpapi -limagehlp -lshlwapi "
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Cannot create temporary file in C:\Users\??苑?AppData\Local\Temp\: Invalid argument
</code></pre>
<p>The TEMP environment varable is</p>
<pre><code>C:\work\ruby-2.1.0-r43936>set TEMP
TEMP=C:\Users\희섭\AppData\Local\Temp
</code></pre>
<p>It seems that miniruby cannot handle encoding properly.</p>
<pre><code>C:\work\ruby-2.1.0-r43936>miniruby -ve "p ENV['TEMP']"
ruby 2.1.0dev (2013-11-30 trunk 43936) [i386-mingw32]
"C:\\Users\\\xED\x9D\xAC\xEC\x84\xAD\\AppData\\Local\\Temp"
C:\work\ruby-2.1.0-r43936>miniruby.exe -ve "p ENV['TEMP'].encoding"
ruby 2.1.0dev (2013-11-30 trunk 43936) [i386-mingw32]
#<Encoding:ASCII-8BIT>
</code></pre>
<p>Whereas, the final ruby can handle encoding properly.</p>
<pre><code>C:\work>ruby -ve "p ENV['TEMP']"
ruby 2.1.0dev (2013-11-30 trunk 43923) [i386-mingw32]
"C:\\Users\\희섭\\AppData\\Local\\Temp"
C:\work>ruby -ve "p ENV['TEMP'].encoding"
ruby 2.1.0dev (2013-11-30 trunk 43923) [i386-mingw32]
#<Encoding:CP949>
</code></pre> Ruby master - Misc #9136 (Assigned): Deprecated Enumerator.new(object, method) bad for BasicObjecthttps://bugs.ruby-lang.org/issues/91362013-11-21T22:18:28Zatlas (Atlas Prime)a7145@live.com
<p>=begin<br>
Documentation it says:</p>
<p>In the second, deprecated, form, a generated Enumerator iterates over the given object using the given method with the given arguments passed.</p>
<p>Use of this form is discouraged. Use Kernel#enum_for or Kernel#to_enum instead.</p>
<pre><code> e = Enumerator.new(ObjectSpace, :each_object)
#-> ObjectSpace.enum_for(:each_object)
</code></pre>
<p>But (({#enum_for})) and (({#to_enum})) are not available to subclasses of (({BasicObject})). In fact, I was defining (({#to_enum})) for a class that is a subclass of (({BasicObject})), and now I get warning of deprecation.<br>
=end</p> Ruby master - Feature #9023 (Assigned): Array#tailhttps://bugs.ruby-lang.org/issues/90232013-10-15T13:28:25Zfuadksd (Fuad Saud)fuadksd@gmail.com
<p>I propose the addition of a <code>tail</code> method to the Array class that returns all elements but the first. It is a pretty common pattern in functional programming, but not limited to - I use it extensively in all kinds of apps/gems. The implementation would be pretty trivial, I won't risk a patch to MRI because I'm uninitiated on ruby core matters, but powerpack gem (<a href="http://github.com/bbatsov/powerpack" class="external">http://github.com/bbatsov/powerpack</a>) implements it in ruby in terms of slices.</p> Ruby master - Bug #9010 (Assigned): ./configure --prefix= cannot handle directories with spaceshttps://bugs.ruby-lang.org/issues/90102013-10-10T07:50:41Zpostmodern (Hal Brodigan)postmodern.mod3@gmail.com
<p>It appears that the linking task fails when the --prefix value contains spaces.</p>
<p>Steps to Reproduce:</p>
<ol>
<li>./configure --prefix="$HOME/foo bar"</li>
<li>make</li>
</ol>
<p>Expected Result: success<br>
Actual Result:</p>
<p>make[2]: Entering directory <code>/home/hal/src/ruby-2.0.0-p247' linking ruby gcc: error: bar/lib: No such file or directory gcc: error: bar/lib: No such file or directory make[2]: *** [ruby] Error 1 make[2]: Leaving directory </code>/home/hal/src/ruby-2.0.0-p247'<br>
make[1]: *** [all] Error 2<br>
make[1]: Leaving directory `/home/hal/src/ruby-2.0.0-p247'<br>
make: *** [build-ext] Error 2</p> Ruby master - Feature #8960 (Assigned): Add Exception#backtrace_locationshttps://bugs.ruby-lang.org/issues/89602013-09-27T20:11:45Zheadius (Charles Nutter)headius@headius.com
<p>All parties agreed this would be useful to add in <a href="https://bugs.ruby-lang.org/issues/7895" class="external">https://bugs.ruby-lang.org/issues/7895</a> and ko1 suggested I file a feature against ruby-trunk. So here it is.</p>
<p>I might be able to come up with a patch, but I'm not sure when. Help wanted.</p>
<p>Can we agree this will go into 2.1?</p> Ruby master - Feature #8959 (Assigned): Allow top level prependhttps://bugs.ruby-lang.org/issues/89592013-09-27T06:24:27Zkyrylo (Kyrylo Silin)silin@kyrylo.org
<p>Since <code>include</code> works on top level, it's reasonable to enable top level<br>
<code>prepend</code> as well.</p>
<p>I've already added a patch (it was partially merged by nobu): <a href="https://github.com/ruby/ruby/pull/395" class="external">https://github.com/ruby/ruby/pull/395</a></p> Ruby master - Feature #8948 (Assigned): Frozen regexhttps://bugs.ruby-lang.org/issues/89482013-09-25T04:02:37Zsawa (Tsuyoshi Sawada)
<p>=begin<br>
I see that frozen string was accepted for Ruby 2.1, and frozen array and hash are proposed in <a href="https://bugs.ruby-lang.org/issues/8909" class="external">https://bugs.ruby-lang.org/issues/8909</a>. I feel there is even more use case for a frozen regex, i.e., a regex literal that generates a regex only once. It is frequent to have a regex within a frequently repeated portion of code, and generating the same regex each time is a waste of resource. At the moment, we can have a code like:</p>
<pre><code>class Foo
RE1 = /pattern1/
RE2 = /pattern1/
RE3 = /pattern1/
def classify
case self
when RE1 then 1
when RE2 then 2
when RE3 then 3
else 4
end
end
end
</code></pre>
<p>but suppose we have a frozen <code>Regexp</code> literal <code>//f</code>. Then we can write like:</p>
<pre><code>class Foo
def classify
case self
when /pattern1/f then 1
when /pattern1/f then 2
when /pattern1/f then 3
else 4
end
end
end
</code></pre>
<p>=end</p> Ruby master - Feature #8850 (Assigned): Convert Rational to decimal stringhttps://bugs.ruby-lang.org/issues/88502013-09-02T10:02:36Znaruse (Yui NARUSE)naruse@airemix.jp
<p>On Ruby 2.1.0, decimal literal is introduced.<br>
It generates Rational but it cannot easily convert to decimal string.<br>
You know, Rational#to_f is related to this but</p>
<ul>
<li>
<p>Float is not exact number<br>
** 0.123456789123456789r.to_f.to_s #=> "0.12345678912345678"</p>
</li>
<li>
<p>it can't handle recursive decimal<br>
** (151/13r).to_f.to_s #=> "11.615384615384615"</p>
</li>
<li>
<p>the method name<br>
** to_decimal<br>
** to_decimal_string<br>
** to_s(format: :decimal)<br>
** extend sprintf</p>
</li>
<li>
<p>how does it express recursive decimal<br>
** (151/13r).to_decimal_string #=> "11.615384..."<br>
** (151/13r).to_decimal_string #=> "11.(615384)"</p>
</li>
</ul>
<p>Example implementation is following.<br>
Its result is<br>
** 0.123456789123456789r.to_f.to_s #=> "0.123456789123456789"<br>
** (151/13r).to_f.to_s #=> "11.(615384)"</p>
<pre><code>class Rational
def to_decimal_string(base=10)
n = numerator
d = denominator
r, n = n.divmod d
str = r.to_s(base)
return str if n == 0
h = {}
str << '.'
n *= base
str.size.upto(Float::INFINITY) do |i|
r, n = n.divmod d
if n == 0
str << r.to_s(base)
break
elsif h.key? n
str[h[n], 0] = '('
str << ')'
break
else
str << r.to_s(base)
h[n] = i
n *= base
end
end
str
end
end
</code></pre> Ruby master - Feature #8839 (Assigned): Class and module should return the class or module that w...https://bugs.ruby-lang.org/issues/88392013-08-31T02:57:19Zheadius (Charles Nutter)headius@headius.com
<p>With the change for <a href="https://bugs.ruby-lang.org/issues/3753" class="external">https://bugs.ruby-lang.org/issues/3753</a>, "def" forms now return the symbolic name of the method defined. Because class and module bodies just return the last expression in their bodies, this means they will now usually end up returning a symbol for the last method defined. This does not seem useful or correct.</p>
<p>I think class and module should return a reference to the class or module just opened. This would make the return value useful and consistent.</p> Ruby master - Feature #8678 (Assigned): Allow invalid string to work with regexphttps://bugs.ruby-lang.org/issues/86782013-07-24T14:47:22Znaruse (Yui NARUSE)naruse@airemix.jp
<p>Legacy Ruby 1.8 could regexp match with broken strings.<br>
People can find characters from binary data on the age.</p>
<p>After Ruby 1.9, Ruby raises Exception if it does regexp match with broken strings.<br>
So it became hard to work with character-wise regexp matching with binary data.</p>
<p>Following patch allows it with the constant Regexp::LOOSEENCODING.</p>
<p>commit eb0111ff7ae3f563ce201c4a5f724f121336d42d<br>
Author: NARUSE, Yui <a href="mailto:naruse@ruby-lang.org" class="email">naruse@ruby-lang.org</a><br>
Date: Mon Jul 22 05:37:44 2013 +0900</p>
<pre><code>* Regexp
* New constant:
* Regexp::ENCODINGLOOSE: declare execute matching even if the target string
is invalid byte sequence. [experimental]
</code></pre>
<p>diff --git a/NEWS b/NEWS<br>
index f5fe388..ade0b03 100644<br>
--- a/NEWS<br>
+++ b/NEWS<br>
@@ -35,6 +35,11 @@ with all sufficient information, see the ChangeLog file.</p>
<ul>
<li>misc
<ul>
<li>Mutex#owned? is no longer experimental.</li>
</ul>
</li>
</ul>
<p>+* Regexp</p>
<ul>
<li>
<ul>
<li>New constant:</li>
</ul>
</li>
<li>
<ul>
<li>Regexp::ENCODINGLOOSE: declare execute matching even if the target string</li>
</ul>
</li>
<li>
<pre><code> is invalid byte sequence. [experimental]
</code></pre>
</li>
<li>
</ul>
<ul>
<li>String
<ul>
<li>New methods:
<ul>
<li>String#scrub and String#scrub! verify and fix invalid byte sequence.<br>
diff --git a/re.c b/re.c<br>
index e5cc79d..230a2e0 100644<br>
--- a/re.c<br>
+++ b/re.c<br>
@@ -256,6 +256,7 @@ rb_memsearch(const void *x0, long m, const void *y0, long n, rb_encoding *enc)</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>#define REG_LITERAL FL_USER5<br>
#define REG_ENCODING_NONE FL_USER6<br>
+#define REG_ENCODING_LOOSE FL_USER7</p>
<p>#define KCODE_FIXED FL_USER4</p>
<p>@@ -263,6 +264,7 @@ rb_memsearch(const void *x0, long m, const void *y0, long n, rb_encoding *enc)<br>
(ONIG_OPTION_IGNORECASE|ONIG_OPTION_MULTILINE|ONIG_OPTION_EXTEND)<br>
#define ARG_ENCODING_FIXED 16<br>
#define ARG_ENCODING_NONE 32<br>
+#define ARG_ENCODING_LOOSE 64</p>
<p>static int<br>
char_to_option(int c)<br>
@@ -1251,7 +1253,8 @@ rb_reg_prepare_enc(VALUE re, VALUE str, int warn)<br>
{<br>
rb_encoding *enc = 0;</p>
<ul>
<li>if (rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {</li>
</ul>
<ul>
<li>if (!(RBASIC(re)->flags & REG_ENCODING_LOOSE) &&</li>
<li>
<pre><code> rb_enc_str_coderange(str) == ENC_CODERANGE_BROKEN) {
rb_raise(rb_eArgError,
"invalid byte sequence in %s",
rb_enc_name(rb_enc_get(str)));
</code></pre>
</li>
</ul>
<p>@@ -2433,6 +2436,9 @@ rb_reg_initialize(VALUE obj, const char *s, long len, rb_encoding *enc,<br>
if (options & ARG_ENCODING_NONE) {<br>
re->basic.flags |= REG_ENCODING_NONE;<br>
}</p>
<ul>
<li>
<p>if (options & ARG_ENCODING_LOOSE) {</p>
</li>
<li>
<pre><code> re->basic.flags |= REG_ENCODING_LOOSE;
</code></pre>
</li>
<li>
<p>}</p>
<p>re->ptr = make_regexp(RSTRING_PTR(unescaped), RSTRING_LEN(unescaped), enc,<br>
options & ARG_REG_OPTION_MASK, err,<br>
@@ -3091,6 +3097,7 @@ rb_reg_options(VALUE re)<br>
options = RREGEXP(re)->ptr->options & ARG_REG_OPTION_MASK;<br>
if (RBASIC(re)->flags & KCODE_FIXED) options |= ARG_ENCODING_FIXED;<br>
if (RBASIC(re)->flags & REG_ENCODING_NONE) options |= ARG_ENCODING_NONE;</p>
</li>
<li>
<p>if (RBASIC(re)->flags & REG_ENCODING_LOOSE) options |= ARG_ENCODING_LOOSE;<br>
return options;<br>
}</p>
</li>
</ul>
<p>@@ -3579,6 +3586,8 @@ Init_Regexp(void)<br>
rb_define_const(rb_cRegexp, "FIXEDENCODING", INT2FIX(ARG_ENCODING_FIXED));<br>
/* see Regexp.options and Regexp.new */<br>
rb_define_const(rb_cRegexp, "NOENCODING", INT2FIX(ARG_ENCODING_NONE));</p>
<ul>
<li>
<p>/* see Regexp.options and Regexp.new */</p>
</li>
<li>
<p>rb_define_const(rb_cRegexp, "LOOSEENCODING", INT2FIX(ARG_ENCODING_LOOSE));</p>
<p>rb_global_variable(&reg_cache);</p>
</li>
</ul>
<p>diff --git a/string.c b/string.c<br>
index 1d784e3..caf0baf 100644<br>
--- a/string.c<br>
+++ b/string.c<br>
@@ -3970,7 +3970,7 @@ str_gsub(int argc, VALUE *argv, VALUE str, int bang)<br>
cp = sp;<br>
str_enc = STR_ENC_GET(str);<br>
rb_enc_associate(dest, str_enc);</p>
<ul>
<li>ENC_CODERANGE_SET(dest, rb_enc_asciicompat(str_enc) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID);</li>
</ul>
<ul>
<li>
<p>/<em>ENC_CODERANGE_SET(dest, rb_enc_asciicompat(str_enc) ? ENC_CODERANGE_7BIT : ENC_CODERANGE_VALID);</em>/</p>
<p>do {<br>
n++;<br>
diff --git a/test/ruby/test_regexp.rb b/test/ruby/test_regexp.rb<br>
index 11e86ec..b8f6897 100644<br>
--- a/test/ruby/test_regexp.rb<br>
+++ b/test/ruby/test_regexp.rb<br>
@@ -8,6 +8,10 @@ class TestRegexp < Test::Unit::TestCase<br>
$VERBOSE = nil<br>
end</p>
</li>
<li>
<p>def u(str)</p>
</li>
<li>
<p>str.dup.force_encoding(Encoding::UTF_8)</p>
</li>
<li>
<p>end</p>
</li>
<li>
<p>def teardown<br>
$VERBOSE = @verbose<br>
end<br>
@@ -958,6 +962,17 @@ class TestRegexp < Test::Unit::TestCase<br>
}<br>
end</p>
</li>
<li>
<p>def test_encoding_loose</p>
</li>
<li>
<p>str = u("\x80\xE3\x81\x82\x81")</p>
</li>
<li>
<p>assert_equal(0, Regexp.new(".", Regexp::LOOSEENCODING) =~ str)</p>
</li>
<li>
<p>assert_equal(1, Regexp.new(u('\p{Any}'), Regexp::LOOSEENCODING) =~ str)</p>
</li>
<li>
<p>assert_equal(1, Regexp.new("\u3042", Regexp::LOOSEENCODING) =~ str)</p>
</li>
<li>
<p>assert_equal(1, Regexp.new(u('\p{Hiragana}'), Regexp::LOOSEENCODING) =~ str)</p>
</li>
<li>
<p>assert_equal(0, Regexp.new(u('\A.\p{Hiragana}.\z'), Regexp::LOOSEENCODING) =~ str)</p>
</li>
<li>
<p>str = u("\xf1\x80\xE3\x81\x82\x81")</p>
</li>
<li>
<p>assert_equal(0, Regexp.new(u('\A..\p{Hiragana}.\z'), Regexp::LOOSEENCODING) =~ str)</p>
</li>
<li>
<p>end</p>
</li>
<li>
<a name="This-assertion-is-for-porting-x2-tests-in-testpypy-of-Onigmo"></a>
<h1 >This assertion is for porting x2() tests in testpy.py of Onigmo.<a href="#This-assertion-is-for-porting-x2-tests-in-testpypy-of-Onigmo" class="wiki-anchor">¶</a></h1>
<p>def assert_match_at(re, str, positions, msg = nil)<br>
re = Regexp.new(re) unless re.is_a?(Regexp)</p>
</li>
</ul> Ruby master - Feature #8576 (Assigned): Add optimized method type for constant value methodshttps://bugs.ruby-lang.org/issues/85762013-06-28T23:22:32ZAnonymous
<p>I've written a patch adding a new method type (VM_METHOD_TYPE_CONSTVAL) for methods that only return a constant value. The patch significantly improves the performance of calls to these types of methods.</p>
<p>I've written a small benchmark script:</p>
<pre><code>require "benchmark"
def foo
1234
end
puts Benchmark.measure {
1_000_000.times do
foo; foo; foo; foo; foo
foo; foo; foo; foo; foo
end
}
</code></pre>
<p>Before patch:</p>
<pre><code>$ ./rb x.rb
0.620000 0.000000 0.620000 ( 0.625130)
</code></pre>
<p>After patch:</p>
<pre><code>$ ./rb x.rb
0.300000 0.000000 0.300000 ( 0.296528)
</code></pre>
<p>The patch is here: <a href="https://github.com/charliesome/ruby/compare/constant-value-methods" class="external">https://github.com/charliesome/ruby/compare/constant-value-methods</a></p> Ruby master - Feature #8295 (Assigned): Float や Rational から(可能であれば)正確な BigDecimal を生成する機能https://bugs.ruby-lang.org/issues/82952013-04-19T17:26:29Zmetanest (Makoto Kishimoto)
<p>=begin<br>
たまに、Float を正確に表現する BigDecimal が欲しいことがあります。</p>
<p>(有効数字の考え方からは邪道ですが。また普通は printf の "%a" による<br>
十六進表現で用が足りることも多いでしょう)</p>
<p>十進でも桁数を必要なだけ伸ばせば、普通の 2 進の浮動小数点数なら正確に<br>
表現できます。また、Rational も分母が 2 と 5 以外の約数を持たない場合に<br>
限っては、正確に BigDecimal に変換できます。</p>
<p>そういった場合に、BigDecimal(0.1, nil) のように精度に nil を指定すれば、<br>
正確な変換が行われたら便利だと思います。Rationalについては、任意の n 進法<br>
を指定して正確な文字列表現にできる場合には変換するという機能(たとえば、<br>
Rational(1, 3) は、3 進法で 0.1 です)というのもありうるかと思いますが、<br>
そこまで実装してはいません。</p>
<p>基本的なアイディアを実装したコードは<br>
((<a href="URL:https://gist.github.com/metanest/5418814" class="external">URL:https://gist.github.com/metanest/5418814</a>))<br>
にあります。名前などのインタフェースには検討の必要が残っていると思います。<br>
=end</p> Ruby master - Feature #8083 (Assigned): Exit status is limited to one-byte values which is invali...https://bugs.ruby-lang.org/issues/80832013-03-13T19:00:42Zrutsky (Vladimir Rutsky)rutsky.vladimir@gmail.com
<p>=begin<br>
Windows uses 32-bit process exit codes so Ruby incorrectly truncates them to one byte:</p>
<p>C:\Ruby193\bin>ruby -e "system('C:\windows\system32\cmd.exe /c exit 255'); puts $?.exitstatus"<br>
255</p>
<p>C:\Ruby193\bin>ruby -e "system('C:\windows\system32\cmd.exe /c exit 256'); puts $?.exitstatus"<br>
0</p>
<p>C:\Ruby193\bin>ruby -e "system('C:\windows\system32\cmd.exe /c exit 257'); puts $?.exitstatus"<br>
1</p>
<p>Similar code works correctly in Python:</p>
<p>C:\Python27>python -c "import subprocess; print subprocess.call('C:\windows\system32\cmd.exe /c exit 255')"<br>
255</p>
<p>C:\Python27>python -c "import subprocess; print subprocess.call('C:\windows\system32\cmd.exe /c exit 256')"<br>
256</p>
<p>C:\Python27>python -c "import subprocess; print subprocess.call('C:\windows\system32\cmd.exe /c exit 257')"<br>
257<br>
=end</p> Ruby master - Feature #8042 (Assigned): Add Addrinfo#socket to create a socket that is not connec...https://bugs.ruby-lang.org/issues/80422013-03-08T08:35:01Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>This adds a socket method to Addrinfo to get a socket that has not been bound or connected to any address for connectionless operation.</p> Ruby master - Feature #8016 (Assigned): Alias __FILE__ and __LINE__ as methodshttps://bugs.ruby-lang.org/issues/80162013-03-05T12:16:30Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
All of the previous issues discussing the new (({Kernel#<strong>dir</strong>})) method (<a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: Kernel#__dir__ (Closed)" href="https://bugs.ruby-lang.org/issues/1961">#1961</a>, <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: __DIR__ revisted (Closed)" href="https://bugs.ruby-lang.org/issues/3346">#3346</a>, <a class="issue tracker-1 status-6 priority-4 priority-default closed" title="Bug: Why __dir__, not __DIR__ (Rejected)" href="https://bugs.ruby-lang.org/issues/7975">#7975</a>), never came to any conclusion regarding the naming inconsistency between the likes of (({<strong>dir</strong>})) and (({<strong>method</strong>})), and the keywords (({<strong>FILE</strong>})) and (({<strong>LINE</strong>})).</p>
<p>Should we not add (({<strong>file</strong>})) and (({<strong>line</strong>})) as methods also, and perhaps deprecate the keywords (({<strong>FILE</strong>})) and (({<strong>LINE</strong>})). This would keep it consistant with all the other double-underscore methods. To most developers who perhaps do not know Ruby as intricately as most of the people on this issue tracker, the inconsistency between (({<strong>dir</strong>})) and (({<strong>FILE</strong>})) is not just confusing by name, but the fact that one is a method and one isn't, is doubly confusing. Definitely not principle of least surprise.</p>
<p>This needs to be addressed in my opinion, either through deprecation of (({<strong>FILE</strong>})) and (({<strong>LINE</strong>})), or by keeping those keywords and simply creating Kernel method equivalents for the sake of a consistant API.</p>
<p>While on the topic, someone also suggested in one of those previous issues, to give (({<strong>dir</strong>})) an optional join argument, so you could do something like this:</p>
<pre><code>__dir__('somefile.txt') # => /Users/admin/somefile.txt
</code></pre>
<p>I'd predict that at least 90% of use cases for (({<strong>dir</strong>})) will involve joining it to another path or filename. I can't see any harm in adding this. The naming inconstancies are my main concern however. This would just be a nice bonus that takes advantage of the fact that (({<strong>dir</strong>})) is a method rather than a keyword.<br>
=end</p> Ruby master - Feature #7739 (Assigned): Define Hash#| as Hash#reverse_merge in Railshttps://bugs.ruby-lang.org/issues/77392013-01-24T21:57:20Zalexeymuranov (Alexey Muranov)
<p>=begin<br>
I suggest for to define (({Hash#|})) as (({Hash#reverse_merge})) in ((<em>Rails</em>)), in my opinion this would correspond nicely to (({Set#|})), to the logical (({#||})) and to the bitwise (({#|})):</p>
<p>{ :a => 1, :b => 2 } | { :b => 1, :c => 2 } # => { :a => 1, :b => 1, :c => 2 }<br>
=end</p> Ruby master - Feature #7518 (Assigned): Fiddle::Pointer#to_str and Fiddle::Pointer#to_int should ...https://bugs.ruby-lang.org/issues/75182012-12-05T23:38:35Zngoto (Naohisa Goto)ngotogenome@gmail.com
<p>There are Fiddle::Pointer#to_str and to_int, to be used for implicit conversion to String and Integer, respectively. I think those implicit conversion methods should be removed.<br>
(Note that there are to_s and to_i, explicit conversion to String and Integer, respectively.)</p>
<p>About to_str: Because Fiddle::Pointer is not always a pointer of char *, and careless conversion of invalid pointer to a string would frequently cause SEGV. So, I think implicit conversion to string is very danger and it should be removed.</p>
<p>About to_int: Unlike to_str, pointer arithmetic methods are available in Fiddle::Pointer, but it lacks many methods for treating it as integer, and I think Fiddle::Pointer is not suitable for implicit conversion to integer.</p> Ruby master - Feature #7436 (Assigned): Allow for a "granularity" flag for backtrace_locationshttps://bugs.ruby-lang.org/issues/74362012-11-26T07:06:40Zsam.saffron (Sam Saffron)sam.saffron@gmail.com
<p>related to <a href="http://bugs.ruby-lang.org/issues/7051" class="external">http://bugs.ruby-lang.org/issues/7051</a></p>
<p>Sometimes one need less information (or more information) associated with backtraces.</p>
<p>It would be nice if one could send in a separate flag informing the VM about the granularity of information required, eg:</p>
<p>caller_locations(0,-current_depth, BacktraceInfo::Label & BacktraceInfo::Lineno)</p>
<p>This allows for one to take quicker backtraces if they need less information, additionally BacktraceInfo::Bindings and BacktraceInfo::Klass could be added which allow you to gather more information for heavy profiling / diagnostics.</p> Ruby master - Feature #7394 (Assigned): Enumerable#find ifnone parameter could be non-callablehttps://bugs.ruby-lang.org/issues/73942012-11-19T12:36:44Zzzak (zzak _)
<p>from github:<br>
<a href="https://github.com/ruby/ruby/pull/186" class="external">https://github.com/ruby/ruby/pull/186</a></p>
<p>In trunk the <code>Enumerable#find</code> method <code>ifnone</code> parameter has to be callable or <code>nil</code>. I found that sometimes I want to return a simple value without wrapping it in a proc. This pull request adds support for non-callable defaults when no items match.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</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>
</code></pre>
<p>The current behavior</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="nb">proc</span> <span class="p">{</span> <span class="ss">:foo</span> <span class="p">})</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span> <span class="o">></span> <span class="mi">3</span> <span class="p">}</span> <span class="c1">#=> :foo</span>
</code></pre>
<p>With patch</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a</span><span class="p">.</span><span class="nf">find</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span> <span class="o">></span> <span class="mi">3</span> <span class="p">}</span> <span class="c1">#=> 0</span>
</code></pre> Ruby master - Feature #7362 (Assigned): Adding Pathname#start_with?https://bugs.ruby-lang.org/issues/73622012-11-15T22:38:40Zaef (Alexander E. Fischer)aef@raxys.net
<p>If a Pathname starts with another Pathname, that means that the former Pathname lies below the latter Pathname, as long as both Pathnames are interpreted from the same location or both are given as absolute.</p>
<p>Therefore I would like to see a method #start_with? just like the one on String but for Pathnames.</p>
<p>If you like the idea, just tell me. I will provide a patch then.</p> Ruby master - Feature #7314 (Assigned): Convert Proc to Lambda doesn't work in MRIhttps://bugs.ruby-lang.org/issues/73142012-11-09T01:30:19Zschneems (Richard Schneeman)
<p>I have code where I need to convert a proc to a lambda (i need to be able to return out of the block). I would expect that passing a proc into a lambda to return a lambda. When I run this code on MRI i do not get the result I would expect</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">my_proc</span> <span class="o">=</span> <span class="nb">proc</span> <span class="p">{</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span> <span class="n">x</span> <span class="p">}</span>
<span class="n">my_lambda</span> <span class="o">=</span> <span class="nb">lambda</span> <span class="o">&</span><span class="n">my_proc</span>
<span class="n">my_lambda</span><span class="p">.</span><span class="nf">lambda?</span>
</code></pre>
<p>The result is <code>false</code> but I would expect it to be <code>true</code></p>
<p>There is currently a way to turn a proc into a lambda in MRI like this:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="k">def</span> <span class="nf">convert_to_lambda</span> <span class="o">&</span><span class="n">block</span>
<span class="n">obj</span> <span class="o">=</span> <span class="no">Object</span><span class="p">.</span><span class="nf">new</span>
<span class="n">obj</span><span class="p">.</span><span class="nf">define_singleton_method</span><span class="p">(</span><span class="ss">:_</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span><span class="p">.</span><span class="nf">method</span><span class="p">(</span><span class="ss">:_</span><span class="p">).</span><span class="nf">to_proc</span>
<span class="k">end</span>
</code></pre>
<p>But this feels like a hack, and is not supported across other implementations. I would expect that passing a proc into a lambda to return a lambda, I believe it is a bug.</p> Ruby master - Feature #7132 (Assigned): Alternation between named / ordered method arguments and ...https://bugs.ruby-lang.org/issues/71322012-10-09T21:17:44ZAnonymous
<p>=begin<br>
Hi everyone. I am using Ruby for >1 year and I would like to share with you my dreams regarding the named method arguments planned for 2.0. Let us imagine a class Thief with 3 properties (name, hit_points and dexterity), which has constructor #new_thief:</p>
<pre><code>new_thief name: "John Fingers", hit_points: 14, dexterity: 15
</code></pre>
<p>I dream about this constructor accepting alternative syntax:</p>
<pre><code>new_thief "John Fingers", hit_points: 14, dexterity: 15
</code></pre>
<p>and accepting synonyms (aliases) :hp for :hit_points and :dex for dexterity:</p>
<pre><code>new_thief "John Fingers", hp: 14, dex: 15
</code></pre>
<p>To explain my motivation, I am creating a DSL in biology. I am facing the challenge of explaining to my colleagues why is it better than their current Java app. Biologists love synonyms, and I'd like the users calling constructors for biological objects to have freedom to use the synonym they like. Of course, I can already achieve it in 1.9.3:</p>
<pre><code>def new_thief *args
oo = args.extract_options!
raise ArgumentError if args[0] and oo[:name] and args[0] != oo[:name]
name = args[0] || oo[:name] || "John Doe"
raise ArgumentError if oo[:hp] and oo[:hit_points] and oo[:hp] != oo[:hit_points]
hp = oo[:hp] || oo[:hit_points] || 9
raise ArgumentError if oo[:dex] and oo[:dexterity] and oo[:dex] != oo[:dexterity]
dex = oo[:dex] || oo[:dexterity] || 11
Thief.new( name: name, hit_points: hp, dexterity: dex )
end
</code></pre>
<p>But I find myself doing this over and over, and even if I write a library to make it easier, it's still too cumbersome.</p>
<p>Proposal no. 1: I propose that alternation between named / ordered arguments and aliases (synonyms) for named method arguments be catered for already by core syntax.</p>
<p>Proposal no. 2: I propose that the syntax for this be as follows:</p>
<pre><code>def new_thief( name=**:name="John Doe", hp: **:hit_points=14, dex: **:dexterity=15 )
Thief.new name: name, hit_points: hp, strength: str, dexterity: dex
end
</code></pre>
<p>where expressions **:arg_name would refer to the named argument :arg_name.</p>
<p>Please judge the two proposals independently. I really dream about having the alternation between named / ordered arguments and aliases for named arguments in Ruby 2.0. But I feel less sure that the syntax **:arg_name that I am proposing is the best possible syntax for this. Mind me, I don't think it is bad, I am just not sure it is <em>best</em>.</p>
<p>PS: Please forgive me suggesting such a complicated feature, while being unable to write a single line in C.<br>
=end</p> Ruby master - Feature #7121 (Assigned): Extending the use of `require'https://bugs.ruby-lang.org/issues/71212012-10-09T10:09:29Zmjones (Morgan Jones)integ3rs@gmail.com
<p>=begin<br>
I was playing with Ruby tonight and thought up an interesting idea to make (({require})) a bit better, so you can load multiple files sequentially using one method call.</p>
<p>Currently, (({require})) supports one argument, and throws a (({TypeError})) if you pass an array:</p>
<p>irb(main):001:0> require %w(json yaml)<br>
TypeError: can't convert Array into String</p>
<p>However, there's a way to patch Kernel that makes it respond to multiple objects passed in an (({Array})).</p>
<p>module Kernel<br>
@@require = method :require</p>
<p>def require *args<br>
args.flatten!<br>
args.collect! do |a|<br>
raise ArgumentError.new "arguments to `require' must be strings or symbols" unless a.is_a?(String) || a.is_a?(Symbol)<br>
@@require.call a.to_s<br>
end</p>
<pre><code> args.length == 1 ? args.first : args
</code></pre>
<p>end<br>
end</p>
<p>The new behavior doesn't actually require the modification of any code that calls (({require})) (pretty much anything, really), and new code can take advantage of the new functionality instantly.</p>
<p>irb> require %w(json yaml)<br>
=> [true, false]<br>
irb> require :pp<br>
=> false<br>
irb> require 'rails'<br>
=> true<br>
irb> require %w(json yaml), :pp, 'rails'<br>
=> [true, false, false, true]<br>
=end</p>
<p>Thanks for considering this.</p> Ruby master - Feature #7087 (Assigned): ::ConditionVariable#wait does not work with Monitor becau...https://bugs.ruby-lang.org/issues/70872012-09-30T00:19:32Zrklemme (Robert Klemme)shortcutter@googlemail.com
<p>See program attached to bug <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: ConditionVariable#wait has meaningless return value (Assigned)" href="https://bugs.ruby-lang.org/issues/7086">#7086</a>: timeout_4 always throws:</p>
<p>ERROR: method "timeout_4": #<NoMethodError: private method `sleep' called for #<a href="Monitor:0x87e49f8" class="external">Monitor:0x87e49f8</a>></p>
<p>$ irb19 -r monitor<br>
irb(main):001:0> Monitor.new.method(:sleep)<br>
=> #<Method: Monitor(Kernel)#sleep><br>
irb(main):002:0> Monitor.instance_methods.grep /sleep/<br>
=> []</p> Ruby master - Feature #7086 (Assigned): ConditionVariable#wait has meaningless return valuehttps://bugs.ruby-lang.org/issues/70862012-09-30T00:14:11Zrklemme (Robert Klemme)shortcutter@googlemail.com
<p>I consider this an API bug: when invoked with a timeout value the caller cannot distinguish from the return value whether the condition has been signaled or the time has run out. Consider how Java does it: <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#await(long,%20java.util.concurrent.TimeUnit)" class="external">http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#await(long,%20java.util.concurrent.TimeUnit)</a> and <a href="http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#awaitUntil(java.util.Date)" class="external">http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/Condition.html#awaitUntil(java.util.Date)</a></p>
<p>There's another issue exhibited through the script but I will create a separate ticket for this.</p> Ruby master - Feature #6973 (Assigned): Add an #integral? method to Numeric to test for whole-num...https://bugs.ruby-lang.org/issues/69732012-09-04T06:03:43Zregularfry (Alex Young)alex@blackkettle.org
<p>Numeric#integer? checks whether an instance is an Integer. It is often useful to check whether the value of a non-Integer variable is actually a whole number, and the #integer? method doesn't help here.</p>
<p>This patch adds Numeric#integral?, which performs this check.</p> Ruby master - Feature #6857 (Assigned): bigdecimal/math BigMath.E/BigMath.exp R. P. Feynman inspi...https://bugs.ruby-lang.org/issues/68572012-08-11T23:46:18Zroyaltm (Rafał Michalski)
<p>The algorythms to calculate E and exp programmed in BigMath module are the very straightforward interpretation of the series 1 + x + x^2/2! +<br>
x^3/3! + ....<br>
Therefore they are slow.</p>
<p>Try it yourself:</p>
<pre><code> require 'bigdecimal/math'
def timer; s=Time.now; yield; puts Time.now-s; end
timer { BigMath.E(1000) } #-> 0.038848
timer { BigMath.E(10000) } #-> 16.526972
timer { BigMath.E(100000) } #-> lost patience
</code></pre>
<p>That's because every iteration divides 1 by n! and the dividend grows extremely fast.</p>
<p>In "Surely You're Joking, Mr. Feynman!" (great book, you should read it if you didn't already) R. P. Feynman said:</p>
<p>"One day at Princeton I was sitting in the lounge and overheard some mathematicians talking about the series for e^x, which is 1 + x + x^2/2! +<br>
x^3/3! Each term you get by multiplying the preceding term by x and dividing by the next number. For example, to get the next term after x^4/4! you<br>
multiply that term by x and divide by 5. It's very simple."</p>
<p>Yes it's very simple indeed. Why it's not been applied in such a great, modern and popular language? Is it because people just forget about simple solutions today?</p>
<p>Here is a Feynman's optimized version of BigMath.E:</p>
<pre><code> def E(prec)
raise ArgumentError, "Zero or negative precision for E" if prec <= 0
n = prec + BigDecimal.double_fig
y = d = i = one = BigDecimal('1')
while d.nonzero? && (m = n - (y.exponent - d.exponent).abs) > 0
m = BigDecimal.double_fig if m < BigDecimal.double_fig
d = d.div(i, m)
i += one
y += d
end
y
end
</code></pre>
<p>Now, let's put it to the test:</p>
<pre><code> (1..1000).all? {|n| BigMath.E(n).round(n) == E(n).round(n) }
=> true
BigMath.E(10000).round(10000) == E(10000).round(10000)
=> true
</code></pre>
<p>What about the speed then?</p>
<pre><code> timer { E(1_000) } #-> 0.003832 ~ 10 times faster
timer { E(10_000) } #-> 0.139862 ~ 100 times faster
timer { E(100_000) } #-> 8.787411 ~ dunno?
timer { E(1_000_000) } #-> ~11 minutes
</code></pre>
<p>The same simple rule might be applied to BigDecimal.exp() which originally uses the same straightforward interpretation of power series.<br>
Feynman's pure ruby version of BigMath.exp (the ext version seems now pointless anyway):</p>
<pre><code> def exp(x, prec)
raise ArgumentError, "Zero or negative precision for exp" if prec <= 0
x = case x
when Float
BigDecimal(x, prec && prec <= Float::DIG ? prec : Float::DIG + 1)
else
BigDecimal(x, prec)
end
one = BigDecimal('1', prec)
case x.sign
when BigDecimal::SIGN_NaN
return BigDecimal::NaN
when BigDecimal::SIGN_POSITIVE_ZERO, BigDecimal::SIGN_NEGATIVE_ZERO
return one
when BigDecimal::SIGN_NEGATIVE_FINITE
x = -x
inv = true
when BigDecimal::SIGN_POSITIVE_INFINITE
return BigDecimal::INFINITY
when BigDecimal::SIGN_NEGATIVE_INFINITE
return BigDecimal.new('0')
end
n = prec + BigDecimal.double_fig
if x.round(prec) == one
y = E(prec)
else
y = d = i = one
while d.nonzero? && (m = n - (y.exponent - d.exponent).abs) > 0
m = BigDecimal.double_fig if m < BigDecimal.double_fig
d = d.mult(x, m).div(i, m)
i += one
y += d
end
end
y = one.div(y, n) if inv
y.round(prec - y.exponent)
end
(1..1000).all? {|n| exp(E(n),n) == BigMath.exp(BigMath.E(n),n) }
# => true
(1..1000).all? {|n| exp(-E(n),n) == BigMath.exp(-BigMath.E(n),n) }
# => true
(-10000..10000).all? {|n| exp(BigDecimal(n)/1000,100) == BigMath.exp(BigDecimal(n)/1000,100) }
# => true
(1..1000).all? {|n| exp(BigMath.PI(n),n) == BigMath.exp(BigMath.PI(n),n) }
# => true
timer { BigMath.exp(BigDecimal('1').div(3, 10), 100) } #-> 0.000496
timer { exp(BigDecimal('1').div(3, 10), 100) } #-> 0.000406 faster but not that really
timer { BigMath.exp(BigDecimal('1').div(3, 10), 1_000) } #-> 0.029231
timer { exp(BigDecimal('1').div(3, 10), 1_000) } #-> 0.004554 here we go...
timer { BigMath.exp(BigDecimal('1').div(3, 10), 10_000) } #-> 12.554197
timer { exp(BigDecimal('1').div(3, 10), 10_000) } #-> 0.189462 oops :)
timer { exp(BigDecimal('1').div(3, 10), 100_000) } #-> 11.914613 who has the patience to compare?
</code></pre>
<p>Arguments with large mantissa should slow down the results of course:</p>
<pre><code> timer { BigMath.exp(BigDecimal('1').div(3, 1_000), 1_000) } #-> 0.119048
timer { exp(BigDecimal('1').div(3, 1_000), 1_000) } #-> 0.066177
timer { BigMath.exp(BigDecimal('1').div(3, 10_000), 10_000) } #-> 68.083222
timer { exp(BigDecimal('1').div(3, 10_000), 10_000) } #-> 29.439336
</code></pre>
<p>Though still two times faster than the ext version.</p>
<p>It seems Dick Feynman was not such a joker after all. I think he was a master in treating lightly "serious" things and treating very seriously things that didn't matter to anybody else.</p>
<p>I'd write a patch for ext version if you are with me. Just let me know.</p> Ruby master - Feature #6842 (Assigned): Add Optional Arguments to String#striphttps://bugs.ruby-lang.org/issues/68422012-08-07T20:24:20Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
One of the very few things I miss from the ol' php days many years ago, was the ability to easily strip arbitrary characters from the ends of string using trim(). Typically, this is whitespace characters, and #strip currently fulfils that use case, but there are also instances where it'd be nice to be able to strip any range of characters from the ends of a string. It goes well with Array#join as often when joining strings with a delimiter, you want to make sure those strings don't already begin or end with that character.</p>
<p>For a full-featured #strip, I'd like to see it have the option of accepting both an Array or String. If a string is provided, each character in that string will be stripped. If an array of strings is given, each element of the array is stripped from the ends of the string - this allows for multi-character delimiters for example. Of course you could go really nuts and supports regex as well (or instead of arrays). To demonstrate the difference...</p>
<pre><code>"<b>bold text</b>".strip("</b>") #=> "old text"
"<b>bold text</b>".strip(["<b>", "</b>"]) #=> "bold text"
"<em><b>bold text</b></em>".strip(["<b>", "</b>", "<em>", "</em>"]) #=> "bold text"
"<em><b>bold text</b></em>".strip(/<\/?.+?>/) #=> "bold text"
</code></pre>
<p>A simple real-world example; this is actually what I was wanting to do right before I came here to raise this feature request, but there's been all kinds of other use cases I've hit in the past:</p>
<pre><code>['some', '/chunked', 'path/'].map{ |v| v.strip('/') }.join('/') #=> "some/chunked/path"
</code></pre>
<p>File#join does something similar, but when you need control over the joining character, this is the way you'd do it.</p>
<p>I've lost count of how many times I've wanted this in Ruby, and there's really no nice workaround. Here's an example on StackOverflow of someone asking how to achieve this stripping behaviour in ruby: <a href="http://stackoverflow.com/questions/3453262/how-to-strip-leading-and-trailing-quote-from-string-in-ruby" class="external">http://stackoverflow.com/questions/3453262/how-to-strip-leading-and-trailing-quote-from-string-in-ruby</a></p>
<p>Obviously, you'd do the same for #lstrip and #rstrip, and all the mutable variants (#strip!, #lstrip!, #rstrip!). Looking forward to others thoughts on this one.<br>
=end</p> Ruby master - Feature #6811 (Assigned): File, Dir and FileUtils should have bang-versions of sing...https://bugs.ruby-lang.org/issues/68112012-07-29T20:34:08Zprijutme4ty (Ilya Vorontsov)prijutme4ty@gmail.com
<p>I found that often write<br>
Dir.mkdir(folder) unless Dir.exist? folder<br>
and similar code for rm, rm_rf and so on<br>
We can simply make bang-versions like<br>
def Dir.mkdir!(folder, permissions=0744)<br>
Dir.mkdir(folder, permissions) unless Dir.exist? folder</p>
<a name="or-another-alternative-Dirmkdirfolder-permissions-rescue-false"></a>
<h1 >or another alternative Dir.mkdir(folder, permissions) rescue false<a href="#or-another-alternative-Dirmkdirfolder-permissions-rescue-false" class="wiki-anchor">¶</a></h1>
<p>end</p> Ruby master - Feature #6695 (Assigned): Configuration for Thread/Fiber creationhttps://bugs.ruby-lang.org/issues/66952012-07-04T14:24:28Zko1 (Koichi Sasada)
<p>=begin<br>
= Abstract</p>
<p>With Feature <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: Thread.new without block. (Assigned)" href="https://bugs.ruby-lang.org/issues/6694">#6694</a>, the following configuration parameters should be allowed for Thread/Fiber creation.</p>
<p>Group1 (new parameters):</p>
<ul>
<li>name: Thread/Fiber name</li>
<li>vm_stack_size: VM's stack size</li>
<li>machine_stack_size: Machine stack size</li>
</ul>
<p>Group2 (existing parameters):</p>
<ul>
<li>local_storage: Initial Thread/Fiber local parameters</li>
<li>thread_group: Thread group (Thread only)</li>
<li>priority: Initial priority Thread#priority= (Thread only)</li>
<li>abort_on_exception: abort on exception (Thread only)</li>
</ul>
<p>= Background</p>
<p>With Feature <a class="issue tracker-2 status-2 priority-4 priority-default" title="Feature: Thread.new without block. (Assigned)" href="https://bugs.ruby-lang.org/issues/6694">#6694</a>, we have a way to specify configurations for Thread creation. Fiber.new() don't receive any parameters now.</p>
<p>= Proposal</p>
<p>This is a initial proposal of configuration for Thread/Fiber creation.</p>
<p>Group1 (new parameters):</p>
<ul>
<li>name: Thread/Fiber name</li>
<li>vm_stack_size: VM's stack size</li>
<li>machine_stack_size: Machine stack size</li>
</ul>
<p>vm_stack_size and machine_stack_size are OS dependent (This means that it will be <em>hint</em> parameter).</p>
<p>Thread#inspect should use `name' parameter.</p>
<p>I also propose a new method Thread#name to get the thread name specified by this parameter.</p>
<p>Group2 (existing parameters):</p>
<ul>
<li>local_storage: Initial Thread/Fiber local parameters</li>
<li>thread_group: Thread group (Thread only)</li>
<li>priority: Initial priority Thread#priority= (Thread only)</li>
<li>abort_on_exception: abort on exception (Thread only)</li>
</ul>
<p>Now, we can specify Group2 parameters only <em>after</em> thread creation. With this parameter, we can specify parameters before thread creation.</p>
<p>=end</p> Ruby master - Feature #6682 (Assigned): Add a method to return an instance attached by a singleto...https://bugs.ruby-lang.org/issues/66822012-07-01T19:22:05Zryoqun (Ryo Onodera)ryoqun@gmail.com
<p>=begin<br>
Currently, there is no easy way to get the attached instance from a singleton class. For MRI, we have to resort to writing an C extension. So it'll be useful to add an instance method to Class to return the attached instance if the given class object is a singleton class.</p>
<p>I'll show what I want in the code-wise with the following code snippet:</p>
<p>text = "I love Ruby."<br>
klass = text.singleton_class</p>
<a name="gt-ltClassString0x000000027383e8gt"></a>
<h1 >=> #<Class:#<a href="String:0x000000027383e8" class="external">String:0x000000027383e8</a>><a href="#gt-ltClassString0x000000027383e8gt" class="wiki-anchor">¶</a></h1>
<p>klass.singleton_instance # <= This is the new method.</p>
<a name="gt-I-love-Ruby"></a>
<h1 >=> "I love Ruby."<a href="#gt-I-love-Ruby" class="wiki-anchor">¶</a></h1>
<p>String.singleton_instance # <= This should return nil because String isn't a singleton class and there is no singleton instance, rather there will be many instances.</p>
<a name="gt-nil"></a>
<h1 >=> nil<a href="#gt-nil" class="wiki-anchor">¶</a></h1>
<p>As for use cases, in my case, I wanted to create a module to add class methods. And it has some state, so must be initialized properly. And it can equally be used by Class#extend and Class#include like this:</p>
<p>module Countable<br>
attr_reader(:count)</p>
<pre><code>class << self
def extended(extended_class)
p("extending #{extended_class}")
super
initialize_state(extended_class)
end
def included(included_class)
p("including #{included_class}")
super
if included_class.singleton_instance # <= Currently, I can't do this.
initialize_state(included_class.singleton_instance)
end
end
private
def initialize_state(object)
p("initializing state of #{object}")
object.instance_variable_set(:@count, 0)
end
end
</code></pre>
<p>end</p>
<p>class Person<br>
extend(Countable)<br>
end</p>
<p>class Book<br>
class << self<br>
include(Countable)<br>
end<br>
end</p>
<p>p(Person.count)<br>
p(Book.count)</p>
<a name="gt-extending-Person"></a>
<h1 >=> "extending Person"<a href="#gt-extending-Person" class="wiki-anchor">¶</a></h1>
<a name="gt-initializing-state-of-Person"></a>
<h1 >=> "initializing state of Person"<a href="#gt-initializing-state-of-Person" class="wiki-anchor">¶</a></h1>
<a name="gt-including-ClassBook"></a>
<h1 >=> "including #<a href="Class:Book" class="external">Class:Book</a>"<a href="#gt-including-ClassBook" class="wiki-anchor">¶</a></h1>
<a name="gt-initializing-state-of-Book"></a>
<h1 >=> "initializing state of Book"<a href="#gt-initializing-state-of-Book" class="wiki-anchor">¶</a></h1>
<a name="gt-0"></a>
<h1 >=> 0<a href="#gt-0" class="wiki-anchor">¶</a></h1>
<a name="gt-0-2"></a>
<h1 >=> 0<a href="#gt-0-2" class="wiki-anchor">¶</a></h1>
<p>Others wanted this functionality as shown by ((<this stackoverflow page|URL:<a href="http://stackoverflow.com/questions/7053455/given-a-ruby-metaclass-how-do-i-get-the-instance-to-which-it-is-attached%3E" class="external">http://stackoverflow.com/questions/7053455/given-a-ruby-metaclass-how-do-i-get-the-instance-to-which-it-is-attached></a>)). Also, I found several actual C-extensions for this kind of functionality on the wild browsing ((<a search result|URL:<a href="https://github.com/search?q=rb_iv_get+__attached__&repo=&langOverride=&start_value=1&type=Code&language=C%3E" class="external">https://github.com/search?q=rb_iv_get+__attached__&repo=&langOverride=&start_value=1&type=Code&language=C></a>)) on github.</p>
<ul>
<li>((<eigen|URL:<a href="https://github.com/elliottcable/refinery/blob/853dcc2254557200d1d6be4cb9c105e8fa9d01a9/ext/eigen/eigen.c#L12%3E" class="external">https://github.com/elliottcable/refinery/blob/853dcc2254557200d1d6be4cb9c105e8fa9d01a9/ext/eigen/eigen.c#L12></a>))</li>
<li>((<mult|URL:<a href="https://github.com/banister/mult/blob/6a1d0bdd383e7e231c5b7c2c718204dfb6ba28ca/ext/mult/mult.c#L43%3E" class="external">https://github.com/banister/mult/blob/6a1d0bdd383e7e231c5b7c2c718204dfb6ba28ca/ext/mult/mult.c#L43></a>))</li>
</ul>
<p>Thanks for creating a great language. Especially I love its meta-programming capability. I'd wish this feature to lead to better meta-programming capability of Ruby.<br>
=end</p> Ruby master - Feature #6671 (Assigned): File.split_all and File.split_roothttps://bugs.ruby-lang.org/issues/66712012-06-30T04:28:57Ztrans (Thomas Sawyer)
<p>=begin<br>
Is there a method for this already?</p>
<p>File.split_all('a/b/c') #=> ['a','b','c']</p>
<p>If not I propose it be added. I've had need of such more than a few times.</p>
<p>It's too bad that File.split can't do this, as it would make more sense. And the current method be called <code>split_base</code>.</p>
<p>In addition <code>split_root</code> would be helpful.</p>
<p>root, path = File.split_all('a/b/c')<br>
root #=> 'a'<br>
path #=> 'b/c'<br>
=end</p> Ruby master - Feature #6611 (Assigned): Comments requested on implementation of set_parse_funchttps://bugs.ruby-lang.org/issues/66112012-06-20T07:46:26Zcjheath (Clifford Heath)clifford.heath@gmail.com
<p>Folk,</p>
<p>I've implemented Twister, a new mutation testing tool to replace Heckle.<br>
It relies on a new hook into the Ruby parser, in order to modify what the<br>
parser thinks it has seen.</p>
<p>Although I have written C extensions before, there are some aspects of<br>
the Ruby core which I'm unfamiliar with and as a result don't know the right<br>
way to handle. I'd like your comments, suggestions and improvements<br>
please.</p>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db</a></p>
<p>In particular, I'd like to know the following:</p>
<ol>
<li>Do you prefer that I move the literal strings (which occur once each) to #defined?</li>
</ol>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R1003" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R1003</a></p>
<ol start="2">
<li>Will this line of code mess up the GC, and how should I fix that?</li>
</ol>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R3853" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R3853</a></p>
<ol start="3">
<li>The set_parse_func is extern though it should be static, but I need to move<br>
the rb_define_global_function out of thread.c. Can someone please tell me where I should<br>
move it to, since there is no Init_Parser?</li>
</ol>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R9029" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L1R9029</a></p>
<p><a href="https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L3R4705" class="external">https://github.com/cjheath/ruby/commit/ea99527feaf7dd06b3e8433ec640238441b188db#L3R4705</a></p>
<ol start="4">
<li>I think I should change set_parse_func to accept a flags argument and a block,<br>
instead of assuming all flags, and taking a Proc. What are the downsides of using a<br>
block instead of a Proc (does this reduce the number of Bindings that get created)?<br>
How do I change set_parse_func to use a block?</li>
</ol>
<p>The initial implementation of Twister is an extension to RSpec which adds the option<br>
"--twist file-or-dir". It's still a bit rough - it needs to change the reporting on the twisted<br>
runs that follow the first (untwisted) run - but it does prove then concept.</p>
<p>Clifford Heath, Data Constellation, <a href="http://dataconstellation.com" class="external">http://dataconstellation.com</a><br>
Agile Information Management and Design.</p> Ruby master - Feature #6452 (Assigned): Allow extend to override class methodshttps://bugs.ruby-lang.org/issues/64522012-05-19T01:58:25Zrosenfeld (Rodrigo Rosenfeld Rosas)rr.rosas@gmail.com
<pre><code>module A
def self.a
'a1'
end
end
module B
def a
'a2'
end
def b
'b'
end
end
A.extend B
assert A.a == 'a2' # this is the change I'm proposing - currently it is 'a1'
assert A.b == 'b'
</code></pre>
<p>Would this change be possible for 3.0?</p> Ruby master - Feature #6376 (Assigned): Feature lookup and checking if feature is loadedhttps://bugs.ruby-lang.org/issues/63762012-04-29T07:03:40Ztrans (Thomas Sawyer)
<p>$LOADED_FEATURES is useful to know what "files" have been loaded. But it doesn't really tell us what "features" have been loaded. If there where were a way to look-up a load path, without actually loading it then it would be possible to compare that to $LOADED_FEATURES and thus know. e.g.</p>
<pre><code>require 'ostruct'
$LOADED_FEATURES #=> [..., "/home/trans/.local/lib/ry/rubies/1.9.3-p125/lib/ruby/1.9.1/ostruct.rb"]
path = require_path('ostruct') #=> "/home/trans/.local/lib/ry/rubies/1.9.3-p125/lib/ruby/1.9.1/ostruct.rb"
$LOADED_FEATURES.include?(path)
</code></pre>
<p>Of course, it would be nice to also have:</p>
<pre><code>required?('ostruct') #=> true
</code></pre>
<p>These methods could be class methods of special module, if it's important to keep the Kernel more tidy, e.g. <code>Ruby.required?('ostruct')</code>.</p>
<p>I am currently working on a project where I need this (and have a couple of other projects that could use it too) and I've had to implement the whole thing from scratch, which isn't simple, nor fast, nor am I 100% confident that it specs exactly to Ruby's own lookup procedure. So it would be much better if Ruby would expose its lookup functionality.</p> Ruby master - Bug #6360 (Assigned): Debug information build even without requesting ithttps://bugs.ruby-lang.org/issues/63602012-04-26T08:46:44Zluislavena (Luis Lavena)luislavena@gmail.com
<p>Hello,</p>
<p>While working on latest RubyInstaller release for 1.9.3-p194 our team detected a bigger shared library and import library being generated.</p>
<p>After further inspection, we found this commit:<br>
<a href="https://github.com/ruby/ruby/commit/ffdaca1d748804f2b5ca2de612f17cf6c78d351b" class="external">https://github.com/ruby/ruby/commit/ffdaca1d748804f2b5ca2de612f17cf6c78d351b</a></p>
<p>Backported r34840 into ruby_1_9_3 branch</p>
<p>The above change added -ggdb to CFLAGS even when was not provided by debugflags configure option.</p>
<p>The following is the comparison of "make" summary with and without the change:</p>
<p>Current trunk:</p>
<pre>
C:\Users\Luis\Projects\oss\ruby\build32>make
CC = gcc
LD = ld
LDSHARED = gcc -shared
CFLAGS = -O3 -fno-omit-frame-pointer -ggdb -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration
XCFLAGS = -include ruby/config.h -include ruby/missing.h -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT
CPPFLAGS = -DFD_SETSIZE=32767 -D_WIN32_WINNT=0x0501 -I. -I.ext/include/i386-mingw32 -I../include -I..
DLDFLAGS = -Wl,--enable-auto-image-base,--enable-auto-import -Wl,--out-implib=libmsvcrt-ruby200.dll.a msvcrt-ruby200.def -Wl,--stack,0x00200000,--enable-auto-import
SOLIBS = msvcrt-ruby200.res.o -lshell32 -lws2_32 -limagehlp
</pre>
<p>Reverting r34840:</p>
<pre>
C:\Users\Luis\Projects\oss\ruby\build32>make
CC = gcc
LD = ld
LDSHARED = gcc -shared -s
CFLAGS = -O3 -fno-omit-frame-pointer -g -Wall -Wextra -Wno-unused-parameter -Wno-parentheses -Wno-long-long -Wno-missing-field-initializers -Wunused-variable -Werror=pointer-arith -Werror=write-strings -Werror=declaration-after-statement -Werror=implicit-function-declaration
XCFLAGS = -include ruby/config.h -include ruby/missing.h -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fvisibility=hidden -DRUBY_EXPORT
CPPFLAGS = -DFD_SETSIZE=32767 -D_WIN32_WINNT=0x0501 -I. -I.ext/include/i386-mingw32 -I../include -I..
DLDFLAGS = -Wl,--enable-auto-image-base,--enable-auto-import -Wl,--out-implib=libmsvcrt-ruby200.dll.a msvcrt-ruby200.def -Wl,--stack,0x00200000,--enable-auto-import
SOLIBS = msvcrt-ruby200.res.o -lshell32 -lws2_32 -limagehlp
</pre>
<p>Notice that -g changed into -ggdb instead.</p>
<p>I think debug symbols shouldn't be compiled unless requested and this is a regression.</p> Ruby master - Feature #6337 (Assigned): FileUtils#synchttps://bugs.ruby-lang.org/issues/63372012-04-22T09:13:25Ztrans (Thomas Sawyer)
<p>=begin<br>
I'd like to see some sort of FileUtils#sync method to sync the contents of one directory with another.</p>
<p>Here is a prototype definition:</p>
<pre><code>#
# Synchronize a destination directory with a source directory.
#
def sync(src, dst, options={})
src_files = Dir[File.join(src, '**', '*')].map{ |f| f.sub(src+'/', '') }
dst_files = Dir[File.join(dst, '**', '*')].map{ |f| f.sub(dst+'/', '') }
removal = dst_files - src_files
rm_dirs, rm_files = [], []
removal.each do |f|
path = File.join(dst, f)
if File.directory?(path)
rm_dirs << path
else
rm_files << path
end
end
rm_files.each { |f| rm(f) }
rm_dirs.each { |d| rmdir(d) }
src_files.each do |f|
src_path = File.join(src, f)
dst_path = File.join(dst, f)
if File.directory?(src_path)
mkdir_p(dst_path)
else
parent = File.dirname(dst_path)
mkdir_p(parent) unless File.directory?(parent)
install(src_path, dst_path)
end
end
end
</code></pre>
<p>I haven't tested this beyond a simple trial. It needs improvement. For one, it probably should be able to handle regular files as arguments too. It also needs to handle verbose and dryrun options properly. Nonetheless, with improvements, would be okay for such to become new feature for FileUtils?</p>
<p>=end</p> Ruby master - Feature #6309 (Assigned): Add a reference queue for weak referenceshttps://bugs.ruby-lang.org/issues/63092012-04-17T17:10:15Zheadius (Charles Nutter)headius@headius.com
<p>Most interesting uses of WeakRef are much harder to do efficiently without a reference queue.</p>
<p>A reference queue, as implemented by the JVM, is basically a queue into which weak references are placed some time after the object they refer to has been collected. The queue can be polled cheaply to look for collected references.</p>
<p>A simple example of usage can be seen in the weakling gem, with an efficient implementation of an ID hash: <a href="https://github.com/headius/weakling/blob/master/lib/weakling/collections.rb" class="external">https://github.com/headius/weakling/blob/master/lib/weakling/collections.rb</a></p>
<p>Notice the _cleanup method is called for every operation, to keep the hash clear of dead references. Failure to have a _cleanup method would mean the hash grows without bounds.</p>
<p>_cleanup cannot be implemented efficiently on MRI at present because there's no reference queue implementation. On MRI, _cleanup would have to perform a linear scan of all stored values periodically to search for dead references. For a heavily used hash with many live values, this becomes a very expensive operation.</p>
<p>It's probably possible to implement reference queues efficiently atop the new ObjectSpace::WeakMap internals, since it already keeps track of weak references and can run code when a weak reference no longer refers to a live object.</p> Ruby master - Feature #6308 (Assigned): Eliminate delegation from WeakRefhttps://bugs.ruby-lang.org/issues/63082012-04-17T17:02:28Zheadius (Charles Nutter)headius@headius.com
<p>WeakRef's delegation features are a really awful pattern that should not be allowed in future versions of Ruby.</p>
<p>WeakRef makes no guarantees as to the liveness of its contained object. It can be collected at any time if there are no strong references to it.</p>
<p>WeakRef currently uses delegation to pass method calls through to the contained object. This encourages a pattern where a WeakRef is passed to methods that expect to have a reference to the underlying object, making it appear to be that object.</p>
<p>Unfortunately, this is <em>never</em> a good idea. Because the object can be collected at any time, you may get a nil reference from <strong>getobj</strong> <em>arbitrarily</em> in code that tries to call methods against the given WeakRef. That means using WeakRef as a delegate will always result in unreliable code, and errors may happen for inexplicable reasons.</p>
<p>I believe Ruby 2.0 should eliminate WeakRef's delegation features and make it a simple reference holder. There's no safe way to use a weak reference except to grab a reference to the object, check that it is alive (non-nil) and then proceed with the use of the object, as follows:</p>
<p>obj = weakref.<strong>getobj</strong><br>
raise AppropriateError unless obj<br>
obj.do_something<br>
obj.do_something_else</p>
<p>Along with eliminating delegation, I would recommend simply making the get method #get, since the uglier #<strong>getobj</strong> is only named that way because it is not delegated.</p> Ruby master - Feature #5970 (Assigned): Add Enumerable#join with same semantics as Array#joinhttps://bugs.ruby-lang.org/issues/59702012-02-05T17:27:39Znow (Nikolai Weibull)now@disu.se
<p>Currently, to join the elements of an Enumerable, you need to call #to_a on the Enumerable and then #join the result. With Enumerable#join one wouldn’t need need to create an intermediate Array.</p> Ruby master - Feature #5945 (Assigned): Add the ability to mark a at_exit as process-local. https://bugs.ruby-lang.org/issues/59452012-01-30T09:59:36Zrobertgleeson (Robert Gleeson)
<p>I'd like to propose a enhancement to <code>at_exit</code>.<br>
It would be nice if you could stop a <code>at_exit</code> handler from running in subprocesses.<br>
You can do this manually with this code:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">parent</span> <span class="o">=</span> <span class="no">Process</span><span class="p">.</span><span class="nf">pid</span>
<span class="nb">at_exit</span> <span class="k">do</span>
<span class="k">if</span> <span class="n">parent</span> <span class="o">==</span> <span class="no">Process</span><span class="p">.</span><span class="nf">pid</span>
<span class="c1"># …</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<p>You can also do it by bypassing handlers:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">at_exit</span> <span class="k">do</span>
<span class="c1"># …</span>
<span class="k">end</span>
<span class="nb">fork</span> <span class="k">do</span>
<span class="nb">exit!</span>
<span class="k">end</span>
</code></pre>
<p>But it would be nice if I could do:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="nb">at_exit</span><span class="p">(</span><span class="kp">false</span><span class="p">)</span> <span class="k">do</span>
<span class="c1"># …</span>
<span class="k">end</span>
</code></pre>
<p>The first approach is kind of ugly, and the second approach isn't sustainable if code outside<br>
your control can <code>fork(…)</code> without calling <code>exit!</code>.</p> Ruby master - Feature #5617 (Assigned): Allow install RubyGems into dediceted directoryhttps://bugs.ruby-lang.org/issues/56172011-11-11T22:12:09Zvo.x (Vit Ondruch)v.ondruch@tiscali.cz
<p>Hello,</p>
<p>I would like to propose my patch, which allows to optionally install RubyGems library into dedicated directory, out of the default Ruby directory structure. This should enable to easily share one RubyGems library by more Ruby implementations and avoids code duplication. I did this patch since Fedora prohibits duplication of system libraries [1], which would be the case if MRI and JRuby are installed in parallel.</p>
<p>Thank you for considering this patch.</p>
<p>Vit</p>
<p>[1] <a href="https://fedoraproject.org/wiki/Packaging:Guidelines#Duplication_of_system_libraries" class="external">https://fedoraproject.org/wiki/Packaging:Guidelines#Duplication_of_system_libraries</a></p> Ruby master - Feature #5582 (Assigned): Allow clone of singleton methods on a BasicObjecthttps://bugs.ruby-lang.org/issues/55822011-11-07T12:34:13Zthinkerbot (Simon Chiang)simon.a.chiang@gmail.com
<p>Currently I do not know of a way to implement something like 'clone' on a BasicObject subclass. This is as close as I've gotten but as you can see the singleton methods are not propagated to the clone.</p>
<pre><code>require 'test/unit'
class Context < BasicObject
def _singleton_class_
class << self
SINGLETON_CLASS = self
def _singleton_class_
SINGLETON_CLASS
end
end
_singleton_class_
end
def _class_
_singleton_class_.superclass
end
def _extend_(mod)
mod.__send__(:extend_object, self)
end
def _initialize_clone_(orig)
# set variables as needed
end
def _clone_
clone = _class_.allocate
clone._initialize_clone_(self)
_singleton_class_.included_modules.each {|mod| clone._extend_ mod }
clone
end
end
class ContextTest < Test::Unit::TestCase
module A
def a
:a
end
end
def test__clone__inherits_modules
context = Context.new
context._extend_ A
clone = context._clone_
assert_equal :a, clone.a
end
def test__clone__inherits_singleton_methods
context = Context.new
def context.a
:a
end
clone = context._clone_
assert_equal :a, clone.a # fails
end
end
</code></pre>
<p>Is there a way to do this that I don't see? If not, then I request that a way be added - perhaps by allowing the singleton_class to be set somehow.</p>
<p>In my case I am using Context as the context for a dsl where methods write to a target (an instance variable). I want to be able to clone a context such that I can have multiple contexts with the same methods, including extensions and singletons, that write to different targets.</p>
<p>Thank you.</p> Ruby master - Feature #5461 (Assigned): Add pipelining to Net::HTTPhttps://bugs.ruby-lang.org/issues/54612011-10-19T07:37:41Zdrbrain (Eric Hodel)drbrain@segment7.net
<p>=begin<br>
The attached patch adds HTTP/1.1 pipelining support to Net::HTTP.</p>
<p>Pipelining is only performed on HTTP/1.1 servers. Net::HTTP will check if the server supports pipelining by using the first request in the list. The user can override this via setting (({http.pipelining = true})).</p>
<p>If a server does not support pipelining or there is an error during pipelining an error will be raised that contains the requests that not have been delivered yet and the responses that have been received.</p>
<p>The patch includes documentation explaining the fine details.</p>
<p>Example:</p>
<p>requests = []<br>
requests << Net::HTTP::Get.new('/images/bug.png')<br>
requests << Net::HTTP::Get.new('/images/date.png')<br>
requests << Net::HTTP::Get.new('/images/find.png')</p>
<p>http = Net::HTTP.new 'localhost'<br>
http.start do<br>
http.pipeline requests do |req, res|<br>
open File.basename(req.path), 'wb' do |io|<br>
io.write res.body<br>
end<br>
end<br>
end</p>
<p>Implementation notes:</p>
<ul>
<li>The current Net::HTTP tests make it very difficult to test bad behavior by servers. In test/net/http/utils.rb I introduced a method to replace Net::BufferedIO with a subclass that can behave incorrectly.</li>
<li>Net::HTTP#pipeline does not fall back to sending requests one-by-one for HTTP/1.1 servers. I think this is acceptable as the user can use existing Net::HTTP code to send requests one-by-one.</li>
</ul>
<p>=end</p> Ruby master - Feature #5434 (Assigned): Allow per-class whitelisting of methods safe to expose th...https://bugs.ruby-lang.org/issues/54342011-10-11T13:11:08Zshyouhei (Shyouhei Urabe)shyouhei@ruby-lang.org
<p>We have following pull-request.</p>
<p><a href="https://github.com/ruby/ruby/pull/50" class="external">https://github.com/ruby/ruby/pull/50</a></p>
<p>How do you feel? I can merge this if you are OK.</p> Ruby master - Feature #5133 (Assigned): Array#unzip as an alias of Array#transposehttps://bugs.ruby-lang.org/issues/51332011-08-01T18:30:03Zmrkn (Kenta Murata)muraken@gmail.com
<p>Array#zip の逆は Array#transpose なんですけど、<br>
この対応関係が非常に分かり難いなと思いました。</p>
<p>Haskell には zip の逆をやる関数として unzip が用意されています。<br>
unzip という名前は、「zip の逆をやりたい」と思ったときに<br>
(transpose よりは) 思い付きやすい名前だと思います。</p>
<p>ということで Array#unzip を Array#transpose のエイリアスとして<br>
導入してはどうでしょう?</p>
<p>以下パッチです:</p>
<p>diff --git a/array.c b/array.c<br>
index 8caad66..dc411b7 100644<br>
--- a/array.c<br>
+++ b/array.c<br>
@@ -4720,6 +4720,7 @@ Init_Array(void)<br>
rb_define_method(rb_cArray, "reject!", rb_ary_reject_bang, 0);<br>
rb_define_method(rb_cArray, "zip", rb_ary_zip, -1);<br>
rb_define_method(rb_cArray, "transpose", rb_ary_transpose, 0);</p>
<ul>
<li>rb_define_alias(rb_cArray, "unzip", "transpose");<br>
rb_define_method(rb_cArray, "replace", rb_ary_replace, 1);<br>
rb_define_method(rb_cArray, "clear", rb_ary_clear, 0);<br>
rb_define_method(rb_cArray, "fill", rb_ary_fill, -1);</li>
</ul> Ruby master - Feature #5129 (Assigned): Create a core class "FileArray" and make "ARGF" its instancehttps://bugs.ruby-lang.org/issues/51292011-08-01T13:57:46Zyimutang (Joey Zhou)
<p>I suggest to create a class "<code>FileArray</code>" whose instance behaves just like <code>ARGF</code> do.<br>
And I think <code>ARGF</code> should be an instance of <code>FileArray</code>. Now when I "<code>p ARGF.class</code>", I get "<code>ARGF.class</code>", so <code>ARGF</code> is an instance of <code>ARGF.class</code>, how meaningless it is.</p>
<p>FileArray methods:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="c1"># create an instance</span>
<span class="n">fa</span> <span class="o">=</span> <span class="no">FileArray</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s1">'a.txt'</span><span class="p">,</span><span class="s1">'b.txt'</span><span class="p">,</span><span class="s1">'c.txt'</span><span class="p">)</span>
<span class="c1"># take many methods from IO</span>
<span class="c1"># most methods from ARGF should be instance methods of ARGF </span>
<span class="n">fa</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">puts</span> <span class="n">line</span> <span class="p">}</span>
<span class="n">fa</span><span class="p">.</span><span class="nf">realines</span>
<span class="n">fa</span><span class="p">.</span><span class="nf">filename</span> <span class="c1"># current file</span>
<span class="c1"># but "argv" not</span>
<span class="nb">p</span> <span class="n">fa</span><span class="p">.</span><span class="nf">file_list</span> <span class="c1"># in ARGF, its ARGF.argv, but #argv is not a proper name for FileArray</span>
<span class="c1"># ARGV array can be modified, adding new file into it, all replace to a new file list.</span>
<span class="c1"># FileArray should add some methods to modify the inner file list.</span>
<span class="n">fa</span><span class="p">.</span><span class="nf">insert</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span><span class="s2">"d.txt"</span><span class="p">)</span>
<span class="n">fa</span><span class="p">.</span><span class="nf">delete</span><span class="p">(</span><span class="s1">'a.txt'</span><span class="p">)</span>
</code></pre>
<p>With <code>FileArray</code>, You can create multiple <code>ARGF</code>-like file arrays simultaneously.</p>
<p>For example, I want to mix two <em>groups</em> of files, not two files:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">a_files</span> <span class="o">=</span> <span class="no">FileArray</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="o">*</span><span class="no">Dir</span><span class="p">.</span><span class="nf">glob</span><span class="p">(</span><span class="s1">'a*.txt'</span><span class="p">))</span>
<span class="n">b_files</span> <span class="o">=</span> <span class="no">FileArray</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="o">*</span><span class="no">Dir</span><span class="p">.</span><span class="nf">glob</span><span class="p">(</span><span class="s1">'b*.txt'</span><span class="p">))</span>
<span class="n">enum_a</span> <span class="o">=</span> <span class="n">a_files</span><span class="p">.</span><span class="nf">each</span>
<span class="n">enum_b</span> <span class="o">=</span> <span class="n">b_files</span><span class="p">.</span><span class="nf">each</span>
<span class="kp">loop</span> <span class="k">do</span>
<span class="nb">puts</span> <span class="n">enum_a</span><span class="p">.</span><span class="nf">next</span>
<span class="nb">puts</span> <span class="n">enum_b</span><span class="p">.</span><span class="nf">next</span>
<span class="k">end</span>
</code></pre> Ruby master - Feature #4818 (Assigned): Add method marshalable?https://bugs.ruby-lang.org/issues/48182011-06-03T11:07:15Zyimutang (Joey Zhou)
<p>Some objects can not be marshaled. Maybe there should be a method to tell it.</p>
<p>hash = Hash.new {|h,k| k * 2}</p>
<p>this hash can't be marshaled because it has a default proc. If existing such method:</p>
<p>Marshal.marshalable?(hash) #=> method "Marshal.marshalable?"<br>
hash.marshalable? #=> method "Kernel#marshalable?"</p>
<p>If you think the method name hard to spell, maybe get a synonym "dumpable?"</p> Ruby master - Feature #4539 (Assigned): Array#zip_withhttps://bugs.ruby-lang.org/issues/45392011-03-30T06:21:32Zcitizen428 (Michael Kohl)citizen428@gmail.com
<p>Inspired by Haskell's <code>zipWith</code> function, I hacked on together for Ruby:</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">zip_with</span><span class="p">([</span><span class="mi">6</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">],</span> <span class="p">:</span><span class="o">+</span><span class="p">)</span> <span class="c1">#=> [7, 7, 7]</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">zip_with</span><span class="p">([</span><span class="mi">6</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">4</span><span class="p">])</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="mi">3</span><span class="o">*</span><span class="n">a</span><span class="o">+</span><span class="mi">2</span><span class="o">*</span><span class="n">b</span> <span class="p">}</span> <span class="c1">#=> [15, 16, 17]</span>
</code></pre>
<p>So far I only have a Ruby version of it:</p>
<p><a href="https://gist.github.com/731702b90757e21cadcb" class="external">https://gist.github.com/731702b90757e21cadcb</a></p>
<p>My questions:</p>
<ol>
<li>
<p>Would this method be considered a worthwhile addition to <code>Array</code>?</p>
</li>
<li>
<p>I've never hacked on the C side of Ruby (read some parts of the source though) and my C is quite rusty. I'd like to change that, would somebody be willing to help me turn this into a proper patch?</p>
</li>
</ol> Ruby master - Feature #4514 (Assigned): #deep_clone and #deep_dup for Objectshttps://bugs.ruby-lang.org/issues/45142011-03-21T19:23:02Zwardrop (Tom Wardrop)tom@tomwardrop.com
<p>=begin<br>
There's often a need to do a deep clone of an object, especially of Hash/Array trees. The typical work around to the lack of this functionality is to Marshall and then Unmarshall (e.g. Marshal::load(Marshal::dump(self)) ), which incurs more overhead than it probably should, and is not very semantic. My suggestion is to either provide #deep_clone and #deep_dup methods on the Object class, or to at least provide equivalent functionality for Hashes and Arrays, such as possibly a #deep_merge method for Hash. The exact implantation is not a large concern of mine; I'll let the experts determine the best method of achieving the desired outcome.<br>
=end</p> Ruby master - Feature #3731 (Assigned): Easier Embedding API for Rubyhttps://bugs.ruby-lang.org/issues/37312010-08-22T07:16:50ZBeoran (Beoran Aegul)beoran@rubyforge.org
<p>=begin<br>
With Ruby 1.9, it has become more difficult to embed Ruby in a C application correctly.<br>
It would be nice if there was a clearly documented and simple C API to embed ruby in C programs.<br>
I know Ruby was not designed from the start to be embedded, but Ruby was used before in several<br>
products as an embedded scripting langauge. It should therefore be possible to do so in a<br>
more straightforward way.</p>
<p>Kind Regards,</p>
<p>B.<br>
=end</p> Ruby master - Feature #3608 (Assigned): Enhancing Pathname#each_child to be lazyhttps://bugs.ruby-lang.org/issues/36082010-07-24T10:27:14Ztaw (Tomasz Wegrzanowski)Tomasz.Wegrzanowski@gmail.com
<p>=begin<br>
Right now it lists entire directory, then yields<br>
every element, that is x.each_child(&b) means x.children.each(&b).</p>
<p>This is too slow for directories mounted over networked file systems etc.,<br>
and there is currently no way to get lazy behaviour, other than leaving<br>
convenient #each_child/#children API and moving to lower level.</p>
<p>With this patch:</p>
<ul>
<li>#children is eager like before, no change here</li>
<li>#each_child becomes lazy</li>
<li>#each_child without block returns lazy enumerator,<br>
so it can be used like this dir.each_child.find(&:symlink?)<br>
without losing laziness.</li>
</ul>
<p>Patch is against trunk. pathname.rb was in lib/ not ext/pathname/lib/<br>
before, but it works either way.</p>
<p>The part to return enumerator when called without a block wouldn't<br>
work in 1.8. If backport is desired, that line would need to be thrown<br>
away, and #children would need to build result array instead<br>
of calling each_child(with_directory).to_a - this would be straightforward.<br>
=end</p> Ruby master - Feature #2631 (Assigned): Allow IO#reopen to take a blockhttps://bugs.ruby-lang.org/issues/26312010-01-23T00:55:49Zdjberg96 (Daniel Berger)
<p>=begin<br>
Please allow IO#reopen to accept a block. This would allow users to temporarily redirect output without having to manually reset the file descriptor. For example:</p>
<p>require 'mkmf'</p>
<a name="stdout-redirected-within-block-only"></a>
<h1 >stdout redirected within block only<a href="#stdout-redirected-within-block-only" class="wiki-anchor">¶</a></h1>
<p>$stdout.reopen('/dev/null') do<br>
if have_header('foo.h')<br>
# Do stuff<br>
end<br>
end</p>
<a name="stdout-now-back-to-its-former-setting"></a>
<h1 >stdout now back to its former setting<a href="#stdout-now-back-to-its-former-setting" class="wiki-anchor">¶</a></h1>
<p>I believe this is both convenient and intuitive when one considers the IO.open also takes a block.</p>
<p>Regards,</p>
<p>Dan<br>
=end</p> Ruby master - Feature #2324 (Assigned): Dir instance methods for relative pathhttps://bugs.ruby-lang.org/issues/23242009-11-02T17:48:30Znobu (Nobuyoshi Nakada)nobu@ruby-lang.org
<p>なかだです。</p>
<p><a href="http://www.ipa.go.jp/security/fy20/reports/tech1-tg/2_05.html" class="external">http://www.ipa.go.jp/security/fy20/reports/tech1-tg/2_05.html</a> を<br>
みて思い出したんですが、相対パスを使う<code>Dir</code>のインスタンスメソッド<br>
はどうでしょうか。実装はmvmブランチにあります。</p>
<pre><code>$ ./ruby -v -e 'p Dir.open("ext"){|d|d.open("extmk.rb"){|f|f.gets}}'
ruby 1.9.1 (2008-12-25 mvm 20976) [i686-linux]
"#! /usr/local/bin/ruby\n"
$ mkdir tmp
$ touch tmp/x tmp/y
$ ./ruby -e 'p Dir.open("tmp"){|d|d.unlink("x")}'
0
$ ls tmp/
y
</code></pre>
<p>--<br>
--- 僕の前にBugはない。<br>
--- 僕の後ろにBugはできる。<br>
中田 伸悦</p>