https://redmine.ruby-lang.org/https://redmine.ruby-lang.org/favicon.ico?17113305112021-04-01T18:13:18ZRuby Issue Tracking SystemRuby master - Feature #17771: String#start_with? should not construct MatchData or set $~https://redmine.ruby-lang.org/issues/17771?journal_id=912262021-04-01T18:13:18Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>I will also point out that this method, like many others, will <em>not</em> always set $~. If you pass a string, it remains whatever it was before:</p>
<pre><code>$ rvm ruby-3.0 do ruby -e '"foo".start_with?("foo"); p $~'
nil
</code></pre>
<p>Avoiding the use of $~ would make this behavior consistent.</p> Ruby master - Feature #17771: String#start_with? should not construct MatchData or set $~https://redmine.ruby-lang.org/issues/17771?journal_id=912272021-04-01T18:25:05Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>I see this behavior was explicitly blessed by matz in <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Feature: String#start_with? with regexp (Closed)" href="https://redmine.ruby-lang.org/issues/13712">#13712</a> but I still believe this is not the best choice.</p>
<p>Around the same time as that discussion, another boolean query method <code>match?</code> was added that explicitly does <em>not</em> set the last match frame variable.</p>
<p>I feel this is inconsistent and the boolean query methods that accept a Regexp should be as fast as possible. If you want a MatchData use methods that provide it.</p> Ruby master - Feature #17771: String#start_with? should not construct MatchData or set $~https://redmine.ruby-lang.org/issues/17771?journal_id=912282021-04-01T18:53:07Zjeremyevans0 (Jeremy Evans)merch-redmine@jeremyevans.net
<ul><li><strong>Tracker</strong> changed from <i>Bug</i> to <i>Feature</i></li><li><strong>Backport</strong> deleted (<del><i>2.5: UNKNOWN, 2.6: UNKNOWN, 2.7: UNKNOWN, 3.0: UNKNOWN</i></del>)</li></ul> Ruby master - Feature #17771: String#start_with? should not construct MatchData or set $~https://redmine.ruby-lang.org/issues/17771?journal_id=912292021-04-01T19:04:24Zenebo (Thomas Enebo)tom.enebo@gmail.com
<ul></ul><p>It really feels like an unintended side-effect of the method. If you write this method and accept a variable then depending on the type of that variable there is either some MatchData (MD) as a side-effect or there isn't. This is inconsistent. If you wanted to explicitly use MD then you have to know what you are supplying. If you know it is a regexp then just writing <code>str =~ /^my_pat/</code> is what you want.</p> Ruby master - Feature #17771: String#start_with? should not construct MatchData or set $~https://redmine.ruby-lang.org/issues/17771?journal_id=912302021-04-01T19:06:48Zheadius (Charles Nutter)headius@headius.com
<ul></ul><p>An alternative to using <code>str =~ /^pat/</code> for a <code>start_with?</code> that provides a MatchData would be to add a <code>start_with</code> that is not a boolean query method.</p> Ruby master - Feature #17771: String#start_with? should not construct MatchData or set $~https://redmine.ruby-lang.org/issues/17771?journal_id=912512021-04-02T10:28:02ZEregon (Benoit Daloze)
<ul></ul><p>I don't think there is a rule that predicate methods only return a boolean and never set <code>$~</code>.<br>
It is the case for <code>String#match</code> vs <code>String#match?</code>, but it doesn't mean it holds for other Regexp methods.<br>
I see it a bit like the use of <code>!</code>, which in the core library is generally only used if there is also a non-<code>!</code> variant (e.g., <code>Array#delete</code>).</p>
<p><code>String#start_with?</code> enables to match a regexp without the need to manually build another regexp like <code>/\A#{regexp}/</code> (from the user point of view, there might be internal caching depending on the regexp engine), so I think that is a valid use case for using <code>start_with?</code> and accessing the MatchData after.</p>
<p>StringScanner has a similar functionality for matching a regexp from the start, as if there was a <code>\A</code>, but does not expose <code>$~</code> directly:<br>
<code>ruby -rstrscan -e 's = StringScanner.new("test string"); s.scan(/(\w)\w+/); p s[1]'</code> => <code>"t"</code>.</p>
<p>That said, I'm not against no longer setting $~ for String#start_with?, but I do worry about the compatibility issue here, especially since it might be quite hard to debug why $~ is suddenly <code>nil</code> or the previous MatchData in the Ruby version changing this behavior.</p> Ruby master - Feature #17771: String#start_with? should not construct MatchData or set $~https://redmine.ruby-lang.org/issues/17771?journal_id=912622021-04-02T14:49:32Zmarcandre (Marc-Andre Lafortune)marcandre-ruby-core@marc-andre.ca
<ul></ul><p>I also believe it is unintended behavior and should be removed.</p>