Ruby Issue Tracking System: Issueshttps://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico?17113305112019-08-22T12:01:33ZRuby Issue Tracking System
Redmine Ruby master - Feature #16115 (Open): Keyword arguments from method calls or ignore extra hash key...https://bugs.ruby-lang.org/issues/161152019-08-22T12:01:33Zkke (Kimmo Lehto)
<p>Just a thought, feel free to insta-close as stupid.</p>
<p>Currently you can do this:</p>
<pre><code>def hello(who:)
puts "Hello, #{who}"
end
opts = { who: 'world' }
hello(who)
</code></pre>
<p>Or:</p>
<pre><code>def hello(who:, **_extra_opts) # without eating extra args, you get ArgumentError (unknown keyword: foo)
puts "Hello, #{who}!"
end
hello(**{ who: 'world', foo: 'bar' })
</code></pre>
<p>Or even this:</p>
<pre><code>def hello(_obj = nil, who: _obj&.who || raise(ArgumentError, "missing who:"))
puts "Hello, #{who}!"
end
hello(OpenStruct.new(who: 'world'))
</code></pre>
<ol>
<li>What if when you passed an object as an argument to a method that only accepts keyword arguments, the methods listed would be called? Then you could do:</li>
</ol>
<pre><code>require 'ostruct'
ostruct = OpenStruct.new(who: 'world, foo: 'bar')
def hello(who:)
puts "Hello, #{who}!"
end
hello(ostruct)
</code></pre>
<ol start="2">
<li>Or perhaps add some sort of "triple splat" that would either a) do the method calling thing described above or b) do the regular hash splatting like <code>**</code> but ignore any keys present that are not listed as keyword arguments:</li>
</ol>
<pre><code>require 'ostruct'
ostruct = OpenStruct.new(who: 'world', foo: 'bar')
def hello(who:)
puts "Hello, #{who}!"
end
# a:
hello(***ostruct) # would call ostruct.who to figure out `who:`
# or b: (currently with ** raises ArgumentError (unknown keyword: foo))
hello(***{ who: 'world', foo: 'bar' }) # would ignore any extra keys
</code></pre>
<p>I think this could open up some possibilities (or a can of worms).</p> Ruby master - Bug #16086 (Closed): OpenStruct method access with a block does not raisehttps://bugs.ruby-lang.org/issues/160862019-08-08T08:56:41Zkke (Kimmo Lehto)
<p>This can cause confusion.</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="o">></span> <span class="no">OpenStruct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">hello: </span><span class="s1">'world'</span><span class="p">).</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="nb">puts</span> <span class="n">k</span><span class="p">.</span><span class="nf">upcase</span> <span class="p">}</span> <span class="c1"># there's no "each" method</span>
<span class="o">=></span> <span class="kp">nil</span>
<span class="o">></span> <span class="no">OpenStruct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">hello: </span><span class="s1">'world'</span><span class="p">).</span><span class="nf">eahc_pair</span> <span class="p">{</span> <span class="o">|</span><span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="o">|</span> <span class="nb">puts</span> <span class="n">k</span><span class="p">.</span><span class="nf">upcase</span> <span class="p">}</span> <span class="c1"># each_pair typo</span>
<span class="o">=></span> <span class="kp">nil</span>
</code></pre>
<p>An undefined key with a block should maybe raise <code>NoMethodError</code> or <code>ArgumentError</code>?</p>
<p>A defined key with a block seems to yield the value, I don't see this being documented:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"> <span class="o">></span> <span class="no">OpenStruct</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="ss">hello: </span><span class="s1">'world'</span><span class="p">).</span><span class="nf">hello</span> <span class="p">{</span> <span class="o">|</span><span class="n">k</span><span class="o">|</span> <span class="nb">puts</span> <span class="n">k</span><span class="p">.</span><span class="nf">upcase</span> <span class="p">}</span>
<span class="no">HELLO</span>
</code></pre>
<p>Maybe it should raise <code>ArgumentError</code> too?</p>
<p>Related: <a href="https://bugs.ruby-lang.org/issues/15515" class="external">https://bugs.ruby-lang.org/issues/15515</a></p> Ruby master - Feature #15899 (Open): String#before and String#afterhttps://bugs.ruby-lang.org/issues/158992019-06-05T07:27:23Zkke (Kimmo Lehto)
<p>There seems to be no methods for getting a substring before or after a marker.</p>
<p>Too often I see and have to resort to variations of:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="n">str</span><span class="p">[</span><span class="sr">/(.+?);/</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="n">str</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s1">';'</span><span class="p">).</span><span class="nf">first</span>
<span class="n">substr</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">str</span><span class="p">.</span><span class="nf">split</span><span class="p">(</span><span class="s1">';'</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">str</span><span class="p">.</span><span class="nf">sub</span><span class="p">(</span><span class="sr">/.*;/</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
<span class="n">str</span><span class="p">[</span><span class="mi">0</span><span class="o">...</span><span class="n">str</span><span class="p">.</span><span class="nf">index</span><span class="p">(</span><span class="s1">';'</span><span class="p">)]</span>
</code></pre>
<p>These create intermediate objects or/and are ugly.</p>
<p>The <code>String#delete_suffix</code> and <code>String#delete_prefix</code> do not accept regexps and thus only can be used if you first figure out the full prefix or suffix.</p>
<p>For this reason, I suggest something like:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="n">str</span> <span class="o">=</span> <span class="s1">'application/json; charset=utf-8'</span>
<span class="o">></span> <span class="n">str</span><span class="p">.</span><span class="nf">before</span><span class="p">(</span><span class="s1">';'</span><span class="p">)</span>
<span class="o">=></span> <span class="s2">"application/json"</span>
<span class="o">></span> <span class="n">str</span><span class="p">.</span><span class="nf">after</span><span class="p">(</span><span class="s1">';'</span><span class="p">)</span>
<span class="o">=></span> <span class="s2">" charset=utf-8"</span>
</code></pre>
<p>What should happen if the marker isn't found? In my opinion, <code>before</code> should return the full string and <code>after</code> an empty string.</p> Ruby master - Bug #15644 (Closed): ThreadsWait problems with Thread#report_on_exceptionhttps://bugs.ruby-lang.org/issues/156442019-03-06T13:20:45Zkke (Kimmo Lehto)
<p>Using ThreadsWait with Thread.report_on_exception is confusing.</p>
<p>ThreadsWait spawns a new thread for waiting on a thread:</p>
<pre><code> # thwait.rb:87
def join_nowait(*threads)
threads.flatten!
@threads.concat threads
for th in threads
Thread.start(th) do |t|
begin
t.join
ensure
@wait_queue.push t
end
end
end
end
</code></pre>
<p>The <code>t.join</code> in <code>ThreadsWait</code> will re-raise the exceptions that happen in the thread being waited on.</p>
<p>If the thread being waited on was using <code>report_on_exception = false</code>, the wait thread will report the exception and the <code>report_on_exception = false</code> effectively did nothing, as you still got an exception report.</p>
<p>If the thread was using <code>report_on_exception = true</code>, both threads will report the exception, so you get it twice.</p>
<p>I think this could be fixed by always setting <code>report_on_exception = false</code> for the wait thread.</p>
<a name="Example-1"></a>
<h1 >Example 1<a href="#Example-1" class="wiki-anchor">¶</a></h1>
<pre><code>require 'thwait'
thread = Thread.new do
Thread.current.report_on_exception = false
sleep 1
raise "Foo"
end
ThreadsWait.all_waits(thread) do |terminated_thread|
puts "Thread #{terminated_thread} terminated"
end
</code></pre>
<a name="Expected-result"></a>
<h2 >Expected result<a href="#Expected-result" class="wiki-anchor">¶</a></h2>
<p>No exception reports</p>
<a name="Actual-result"></a>
<h2 >Actual result<a href="#Actual-result" class="wiki-anchor">¶</a></h2>
<p>The wait thread will report the exception:</p>
<pre><code>#<Thread:0x00007fa57d092d68@/Users/user/.rbenv/versions/2.6.1/lib/ruby/2.6.0/thwait.rb:91 run> terminated with exception (report_on_exception is true):
</code></pre>
<a name="Example-2"></a>
<h1 >Example 2<a href="#Example-2" class="wiki-anchor">¶</a></h1>
<pre><code>require 'thwait'
thread = Thread.new do
sleep 1
raise "Foo"
end
ThreadsWait.all_waits(thread) do |terminated_thread|
puts "Thread #{terminated_thread} terminated"
end
</code></pre>
<a name="Expected-result-2"></a>
<h2 >Expected result<a href="#Expected-result-2" class="wiki-anchor">¶</a></h2>
<p>One exception report</p>
<a name="Actual-result-2"></a>
<h2 >Actual result<a href="#Actual-result-2" class="wiki-anchor">¶</a></h2>
<p>Two exception reports:</p>
<pre><code>#<Thread:0x00007f9f83053320@test.rb:3 run> terminated with exception (report_on_exception is true):
#<Thread:0x00007f9f830530a0@/Users/user/.rbenv/versions/2.6.1/lib/ruby/2.6.0/thwait.rb:91 run> terminated with exception (report_on_exception is true):
Traceback (most recent call last):
</code></pre> Ruby master - Bug #15596 (Rejected): Kernel.warn without arguments should do the same as Kernel.w...https://bugs.ruby-lang.org/issues/155962019-02-08T13:05:40Zkke (Kimmo Lehto)
<p>Kernel.warn without arguments does not print an empty line to $stderr.</p>
<p>This is inconsistent with <code>Kernel.puts</code> and it feels weird, because it does not act like a regular Ruby method would (if it was written in Ruby instead of C, it would probably be defined like <code>def warn(msg = nil)</code> and calling it with or without nil as argument would make no difference)</p>
<a name="Expected-behavior"></a>
<h3 >Expected behavior:<a href="#Expected-behavior" class="wiki-anchor">¶</a></h3>
<pre><code>irb(main):001:0> warn nil
=> nil
irb(main):002:0> warn
=> nil
</code></pre>
<a name="Actual-behavior"></a>
<h3 >Actual behavior:<a href="#Actual-behavior" class="wiki-anchor">¶</a></h3>
<pre><code>irb(main):001:0> warn nil
=> nil
irb(main):002:0> warn
=> nil
</code></pre> Ruby master - Feature #15538 (Third Party's Issue): Erb indenting / unindenting https://bugs.ruby-lang.org/issues/155382019-01-15T13:35:10Zkke (Kimmo Lehto)
<p>In <code>Erb</code>, would it be possible to add a new tag that would indent the following content to match the depth of the tag? The tag could be <code><%~</code> (to resemble the <code><<~EOS</code> squiggy heredoc).</p>
<a name="Reason"></a>
<h2 >Reason<a href="#Reason" class="wiki-anchor">¶</a></h2>
<p>Something like this would be easy to follow:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="mi">1</span>
<span class="o"><</span><span class="sx">%- [2, 3, 4].each do |num| -%>
<%- unless num == 3 -%></span>
<span class="o"><</span><span class="sx">%= num %>
<%- end -%>
<%- end -%>
5
</span></code></pre>
<p>But unfortunately it will render with "extra" indentation:</p>
<pre><code>1
2
4
5
</code></pre>
<p>Currently, to avoid this, you have to write your template using either no indentation:</p>
<pre><code>1
<%- [2, 3, 4].each do |num| -%>
<%- unless num == 3 -%>
<%= num %>
<%- end -%>
<%- end -%>
5
</code></pre>
<p>Or a weird jumpy indentation:</p>
<pre><code>1
<%- [2, 3, 4].each do |num| -%>
<%- unless num == 3 -%>
<%= num %>
<%- end -%>
<%- end -%>
5
</code></pre>
<p>With the <code><%~</code> it could be written as:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="mi">1</span>
<span class="o"><</span><span class="sx">%~ [2, 3, 4].each do |num| -%>
<%- unless num == 3 -%>
<%= num %>
<%- end -%>
<%~</span> <span class="k">end</span> <span class="o">-</span><span class="sx">%>
5
</span></code></pre>
<p>And it would output as desired without the "extra" indentation:</p>
<pre><code>1
2
4
5
</code></pre>
<p>Another example:</p>
<pre><code><%= "abcd" %> <%~ [1.2.3].each do |num| -%>
<%= num %>
<%~ end -%>
</code></pre>
<p>would produce:</p>
<pre><code>abcd 1
2
3
</code></pre>
<h2>Using with <code>=</code>
</h2>
<p>It would also be handy if the <code>~</code> could be used in <code><%=</code> statements, perhaps as <code><%~=</code>. This would be excellent for example when templating YAML's:</p>
<pre><code class="yaml syntaxhl" data-language="yaml"><span class="s"><%- bars = %w(abc def)" -%></span>
<span class="na">foo</span><span class="pi">:</span>
<span class="na">bar</span><span class="pi">:</span>
<span class="s"><%~= bars.map { |bar| "-</span> <span class="c1">#{bar}\n" } %></span>
</code></pre>
<p>Which would reindent the statement outcome to produce something like:</p>
<pre><code class="yaml syntaxhl" data-language="yaml"><span class="na">foo</span><span class="pi">:</span>
<span class="na">bar</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">abc</span>
<span class="pi">-</span> <span class="s">def</span>
</code></pre>
<p>This would require these new tags:</p>
<ol>
<li>
<code><%~</code> begin a code block and begin or end reindentation mode. content produced inside the block will be reindented to the depth of the <code><</code> character in <code><%~</code>. If the indentation mode was already active due to a previous <code><%~</code>, it ends the indentation mode.</li>
<li>
<code><%~=</code> like regular <code><%=</code> but multiline strings will be reindented to the column of the <code><</code> character</li>
</ol> Ruby master - Bug #13558 (Closed): Array#insert does not typecheck the position argument if it's ...https://bugs.ruby-lang.org/issues/135582017-05-12T09:26:34Zkke (Kimmo Lehto)
<p><strong>rb_ary_insert</strong> does this:</p>
<pre><code class="c syntaxhl" data-language="c"><span class="k">if</span> <span class="p">(</span><span class="n">argc</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="n">ary</span><span class="p">;</span>
</code></pre>
<p>For Ruby this means:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="p">[].</span><span class="nf">insert</span><span class="p">(</span><span class="s2">"foo"</span><span class="p">)</span>
<span class="o">=></span> <span class="p">[]</span>
<span class="o">></span> <span class="p">[].</span><span class="nf">insert</span><span class="p">(</span><span class="no">Exception</span><span class="p">.</span><span class="nf">new</span><span class="p">)</span>
<span class="o">=></span> <span class="p">[]</span>
</code></pre>
<p>I would expect this to raise a TypeError. The problem here is that if you forget the position argument, because perhaps you thought Array#insert would be an alias for Array#unshift, you get unexpected results and no errors.</p>
<p>If you try to insert two items it fails nicely:</p>
<pre><code class="ruby syntaxhl" data-language="ruby"><span class="o">></span> <span class="p">[].</span><span class="nf">insert</span><span class="p">(</span><span class="s1">'foo'</span><span class="p">,</span> <span class="s1">'foo'</span><span class="p">)</span>
<span class="no">TypeError</span><span class="p">:</span> <span class="n">no</span> <span class="n">implicit</span> <span class="n">conversion</span> <span class="n">of</span> <span class="no">String</span> <span class="n">into</span> <span class="no">Integer</span>
</code></pre>