https://bugs.ruby-lang.org/https://bugs.ruby-lang.org/favicon.ico2013-10-08T03:04:22ZRuby Issue Tracking SystemRuby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423162013-10-08T03:04:22ZKoichi Sasada
<ul><li><strong>Category</strong> set to <i>core</i></li><li><strong>Assignee</strong> set to <i>Yukihiro Matsumoto</i></li></ul><blockquote>
<p>If we do not want to overload the existing .freeze method in this way, we could follow suggestions in <a href="http://bugs.ruby-lang.org/issues/8977">http://bugs.ruby-lang.org/issues/8977</a> to add a new &quot;frozen&quot; method (or some other name) that the compiler would understand. </p>
</blockquote>
<p>I like this idea. No compatibility issue.</p>
<p>(except naming issue)</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423172013-10-08T03:10:04ZCaleb Thompsoncaleb@calebthompson.io
<ul></ul><p>Optimizing the #freeze or #frozen methods to do this make a lot more sense to me<br>
than the <code>&quot;&quot;f</code> suffix to me.</p>
<p>I&#39;m +1 on #frozen and preventing redefinition of that method, but I further<br>
propose that we raise an error if redefining frozen rather than silently<br>
ignoring it, which would be very surprising.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423182013-10-08T03:18:37ZCharlie Somervillecharliesome@ruby-lang.org
<ul></ul><p>+1 for optimized String#freeze as it will work on previous versions of Ruby:</p>
<p>I&#39;ve written a patch implementing this feature: <a href="https://gist.github.com/charliesome/6836600">https://gist.github.com/charliesome/6836600</a></p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423192013-10-08T03:27:29ZCharles Nutterheadius@headius.com
<ul></ul><p>=begin<br>
I am leaning toward #frozen if we want a new name... as in &quot;give me the frozen version of this string&quot;. I know that there was some concern that &quot;frozen&quot; was too similar to &quot;freeze&quot; in <a href="http://bugs.ruby-lang.org/issues/8977">http://bugs.ruby-lang.org/issues/8977</a> but it still feels like the best name.</p>
<p>If we can&#39;t do a new name that refers to freezing, I&#39;d rather just stick with .freeze.</p>
<p>And I still kinda like ~@ :-)</p>
<p>class String<br>
alias ~@ freeze<br>
end</p>
<p>...although there&#39;s operator precedence problems (puts ~&quot;str&quot;.frozen? does not work).<br>
=end</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423202013-10-08T05:33:49ZBenoit Daloze
<ul></ul><p>I am happy to see another discussion on this, I feel &quot;str&quot;f is just a hack.</p>
<p>I strongly agree and think #freeze is the right name.</p>
<p>On the aesthetics side, I personally dislike prefix/suffix forms, they feel like u&#39;str&#39; in python which just makes me think it does not support the right strings by default. I kind of like %f{ ... } but #freeze fits even more in Ruby I think, even if a bit long but at least its semantics are clear.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423222013-10-08T07:59:09ZEric Wongnormalperson@yhbt.net
<ul></ul><p>&quot;headius (Charles Nutter)&quot; <a href="mailto:headius@headius.com">headius@headius.com</a> wrote:</p>
<blockquote>
<p>I propose that we eliminate the new &quot;f&quot; suffix and just make the compiler<br>
smart enough to see literal strings with .frozen the same way.</p>
<p>So this code:</p>
<p>str = &quot;mystring&quot;.freeze</p>
<p>Would be equivalent in the compiler to this code:</p>
<p>str = &quot;mystring&quot;f</p>
<p>And the fstring table would still be used to return pooled instances.</p>
</blockquote>
<p>This is a great idea IMHO. The backwards compatibility is a huge win<br>
and I think this is the best idea so far regarding frozen strings.</p>
<blockquote>
<p>IMPLEMENTATION NOTES:</p>
<p>The fstring table already exists on master and would be used for these<br>
pooled strings. An open question is whether the compiler should<br>
forever optimize &quot;str&quot;.frozen to return the pooled version or whether<br>
it should check (inline-cache style) whether String#freeze has been<br>
replaced. I am ok with either, but the best potential comes from<br>
ignoring String#freeze redefinitions...or making it impossible to<br>
redefine String#freeze.</p>
</blockquote>
<p>Initially (a few minutes ago), I thought it&#39;d be better to inline-cache<br>
to minimize surprise/keep compatibility. And maybe spew a loud warning on<br>
String#freeze redefinition.</p>
<p>But thinking about this more, string literals are already special.<br>
String#initialize is already ignored for string literals, so perhaps<br>
#freeze may be unredefinedable, as well.</p>
<blockquote>
<p>If we do not want to overload the existing .freeze method in this way,<br>
we could follow suggestions in <a href="http://bugs.ruby-lang.org/issues/8977">http://bugs.ruby-lang.org/issues/8977</a><br>
to add a new &quot;frozen&quot; method (or some other name) that the compiler<br>
would understand.</p>
</blockquote>
<p>I think having only .freeze is better (especially for compatibility) and<br>
a new .frozen method would be of minimal benefit.<br>
(But you know Ruby far better than I do)</p>
<blockquote>
<p>I also propose one alternative method name: the unary ~ operator.</p>
<p>There is no ~ on String right now, and it has no meaning for strings that we&#39;d be overriding. So the following two lines would be equivalent:</p>
<p>str = ~&quot;mystring&quot;<br>
str = &quot;mystring&quot;f</p>
</blockquote>
<p>I hate this alternative &quot;name&quot;. It&#39;s too ambiguous/confusing<br>
(consider: ~&quot;username&quot; or /regexp/ =~ ~&quot;foo&quot;),<br>
not backwards compatible, and hard to search for documentation on.</p>
<p>I think a beginner new to the language would be very confused by this.<br>
You have my strong support of #freeze, but my strongest disapproval of ~</p>
<blockquote>
<p>JUSTIFICATION:</p>
<p>Making the compiler aware of normal method-based String freezing has the following advantages:</p>
<ul>
<li>It will parse in all versions of Ruby.</li>
<li>It will be equivalent in all versions of Ruby other than the fstring pooling.</li>
<li>It extends neatly to Array and Hash; the compiler can see Array or Hash with literal elements and return the same object.</li>
<li>It does not require a pragma (<a href="http://bugs.ruby-lang.org/issues/8976">http://bugs.ruby-lang.org/issues/8976</a> )</li>
<li>It looks like Ruby.</li>
</ul>
</blockquote>
<p>Amen!</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423402013-10-09T04:24:08ZMiguel Cambamiguel.camba@gmail.com
<ul></ul><p>I have another idea What about wrap strings in double backquotes or accents?</p>
<p>&quot;this is an interpolable string&quot;<br>
&#39;this is an uninterpolable string&#39;<br>
<code>this is a frozen string</code> =&gt; double backquoute<br>
´this is also a frozen string´ =&gt; simple accent</p>
<p>Accents looks elegant, but I don&#39;t know if they are cumbersome in some keyboard distributions and I am not sure if they al limited to UTF8 code, but double backquote seems easy to add to the parser and feels pretty natural.</p>
<p>Whatever character(s) you like the most, (<code>string</code>, ´sting´, <sup>string<sup>,</sup></sup> ~string~, \string) I like the idea to be used as a wrapper, not adding a special symbol before or after the string definition.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423432013-10-09T05:35:26ZCharles Nutterheadius@headius.com
<ul></ul><p>cibernox (Miguel Camba) wrote:</p>
<blockquote>
<p>I have another idea What about wrap strings in double backquotes or accents?</p>
<p>&quot;this is an interpolable string&quot;<br>
&#39;this is an uninterpolable string&#39;<br>
<code>this is a frozen string</code> =&gt; double backquoute</p>
</blockquote>
<p>I don&#39;t think the parser can distinguish this from normal backquotes that are empty...but there&#39;s no value to supporting empty shelling-out backquotes, so maybe it&#39;s not hard to special-case it.</p>
<p>if backquotes_contains_content<br>
parse_as_normal_backquote<br>
else<br>
parse_as_frozen_string<br>
end</p>
<p>Or something :-D</p>
<blockquote>
<p>´this is also a frozen string´ =&gt; simple accent</p>
</blockquote>
<p>Not on standard US keyboards, so this will never fly.</p>
<blockquote>
<p>Whatever character(s) you like the most, (<code>string</code>, ´sting´, <sup>string<sup>,</sup></sup> ~string~, \string) I like the idea to be used as a wrapper, not adding a special symbol before or after the string definition.</p>
</blockquote>
<p>Agreed. I still like just adding smarts for .freeze over any of the other options.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423442013-10-09T06:04:58ZMiguel Cambamiguel.camba@gmail.com
<ul></ul><p>Yep, we can discard the accent.</p>
<p>The double pipe can be tricky is you want to set a frozen string as default value of a block argument.<br>
The double ^ has confict with the xor operator.<br>
The double ~ has conflict with the complement operator<br>
The double backslash seems fancy, like an opposite of regex, but since can also be used to break lines and escape characters. And probably is more difficult to parse . You tell me.</p>
<p>I know nothing about the parser internals, but the double backquote feels like a string and seems reasonable easy to implement. Seems the best option.</p>
<p>This idea can just coexist with the .freeze method. Is a bit of syntax sugar.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423472013-10-09T06:47:11ZCharlie Somervillecharliesome@ruby-lang.org
<ul></ul><p>I feel like we&#39;re getting a bit off topic in this thread.</p>
<p>The main benefit of optimizing String#freeze is maintaining backwards compatibility with older Rubies. Think of it as a kind of &#39;progressive enhancement&#39;.</p>
<p>Introducing new syntax or a new method completely removes any backwards compatibility benefits and will mean that most Ruby code will not be able to use this syntax for quite some time.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423482013-10-09T06:56:20ZSam Saffronsam.saffron@gmail.com
<ul></ul><p>I am actually very concerned about compiler tricks with freeze cause it leads to non-obvious code. </p>
<p>x = &quot;hello&quot;.freeze<br>
y = &quot;hello&quot;.freeze<br>
x.object_id</p>
<blockquote>
<p>10<br>
x.object_id == y.object_id</p>
</blockquote>
<p>a = &quot;hello&quot;<br>
a.object_id</p>
<blockquote>
<p>100<br>
a.freeze<br>
a.object_id <br>
100 # must be 100</p>
</blockquote>
<hr>
<p>So the way #freeze operates then depends on where it is being executed, I dislike that. </p>
<p>Much prefer just adding #frozen, we can implement it sort of cleanly in 2.0 (except for GC hooking) and simply alias #freeze in 1.9 and earlier. </p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423532013-10-09T09:25:53ZCharles Nutterheadius@headius.com
<ul></ul><p>sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>I am actually very concerned about compiler tricks with freeze cause it leads to non-obvious code. </p>
<p>x = &quot;hello&quot;.freeze<br>
y = &quot;hello&quot;.freeze<br>
x.object_id</p>
<blockquote>
<p>10<br>
x.object_id == y.object_id</p>
</blockquote>
</blockquote>
<p>I don&#39;t think you should <em>ever</em> rely on this to be true, since it won&#39;t be on older Ruby impls or impls that don&#39;t yet have #freeze optimizations. Even Java, with its interned Strings, strongly discourages <em>ever</em> using object identity to compare strings. IDEs even flag it as a warning.</p>
<blockquote>
<p>a = &quot;hello&quot;<br>
a.object_id</p>
<blockquote>
<p>100<br>
a.freeze<br>
a.object_id <br>
100 # must be 100<br>
...<br>
So the way #freeze operates then depends on where it is being executed, I dislike that. </p>
</blockquote>
<p>Much prefer just adding #frozen, we can implement it sort of cleanly in 2.0 (except for GC hooking) and simply alias #freeze in 1.9 and earlier.</p>
</blockquote>
<p>So here&#39;s the same question I asked in the #frozen feature: why can&#39;t #freeze just use the fstring table?</p>
<ul>
<li>fstrings will GC and clear themselves from that table</li>
<li>large strings put into the table will take up no more space than if they were not frozen</li>
</ul>
<p>So #freeze <em>could</em> do what you suggest here and always use the fstring table. In the &quot;literal&quot;.freeze case, the compiler could do additional magic to go to the table immediately.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423572013-10-09T11:29:17ZEric Wongnormalperson@yhbt.net
<ul></ul><p>&quot;headius (Charles Nutter)&quot; <a href="mailto:headius@headius.com">headius@headius.com</a> wrote:</p>
<blockquote>
<p>So here&#39;s the same question I asked in the #frozen feature: why can&#39;t<br>
#freeze just use the fstring table?</p>
</blockquote>
<p>That would be an interesting experiment. After all, it is #freeze and<br>
not #freeze!, so maybe we have some leverage there.</p>
<blockquote>
<ul>
<li>fstrings will GC and clear themselves from that table</li>
</ul>
</blockquote>
<p>I think this needs some work for the non-parser case, there seems to<br>
be a bad interaction with lazy sweep. My analysis of my failed<br>
patch for Feature <a class="issue tracker-2 status-5 priority-3 priority-lowest closed" title="string keys for hash literals should use fstrings (Closed)" href="https://bugs.ruby-lang.org/issues/8998">#8998</a>:<br>
<a href="http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net">http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net</a></p>
<p>I also get (identical?) segfaults with the following:</p>
<p>diff --git a/object.c b/object.c<br>
--- a/object.c<br>
+++ b/object.c<br>
@@ -1029,6 +1029,8 @@ VALUE<br>
rb_obj_freeze(VALUE obj)<br>
{<br>
if (!OBJ_FROZEN(obj)) {<br>
+ if (TYPE(obj) == T_STRING)<br>
+ return rb_fstring(obj);<br>
OBJ_FREEZE(obj);<br>
if (SPECIAL_CONST_P(obj)) {<br>
if (!immediate_frozen_tbl) {</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423582013-10-09T12:01:55ZSam Saffronsam.saffron@gmail.com
<ul></ul><p>@hedius </p>
<p>What happens when a string pointer leaks out to a c extension? </p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423632013-10-09T14:46:55ZCharles Nutterheadius@headius.com
<ul></ul><p>sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>@hedius </p>
<p>What happens when a string pointer leaks out to a c extension?</p>
</blockquote>
<p>This question applies equally to &quot;str&quot;f logic. I&#39;m not sure what the answer is, because I don&#39;t know how frozen strings in @charliesome&#39;s patch interact with C extensions.</p>
<p>I don&#39;t think making freeze act like Java&#39;s String#intern has any better or worse interaction with C extensions than normal &quot;str&quot;f fstrings interact with C extensions.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423642013-10-09T14:48:14ZCharles Nutterheadius@headius.com
<ul></ul><p>headius (Charles Nutter) wrote:</p>
<blockquote>
<p>This question applies equally to &quot;str&quot;f logic. I&#39;m not sure what the answer is, because I don&#39;t know how frozen strings in @charliesome&#39;s patch interact with C extensions.</p>
</blockquote>
<p>Actually, it occurred to me that the interaction with C extensions is actually even simpler; if a string leaks out to C exts, it&#39;s no worse than <em>any</em> string leaking out. The only difference is that the C ext would still have a reference while the fstring table does not. So I think it&#39;s no worse than current interaction with strings.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=423652013-10-09T14:53:05ZCharles Nutterheadius@headius.com
<ul></ul><p>normalperson (Eric Wong) wrote:</p>
<blockquote>
<p>&quot;headius (Charles Nutter)&quot; <a href="mailto:headius@headius.com">headius@headius.com</a> wrote:</p>
<blockquote>
<p>So here&#39;s the same question I asked in the #frozen feature: why can&#39;t<br>
#freeze just use the fstring table?</p>
</blockquote>
<p>That would be an interesting experiment. After all, it is #freeze and<br>
not #freeze!, so maybe we have some leverage there.</p>
</blockquote>
<p>I think we do. The worst case scenario is that <em>while referenced</em> we have more entries in the table, which may include strings that become &quot;shady&quot; and pass out to C exts. But those strings would stay alive under the current definition of &quot;shady&quot; and even under older Ruby versions with a purely conservative GC the effects are no worse.</p>
<p>So basically:</p>
<ul>
<li>If the string is long lived normally, it will take up X bytes for its lifetime.</li>
<li>If the string gets stored in the fstring table, it will last no longer than it would without the fstring table.</li>
<li>If the string is short-lived, it will have a bit more overhead for dealing with fstring table, but very little; hash calculation and table management at most.</li>
</ul>
<p>It seems acceptable to have #freeze basically be Java&#39;s #intern.</p>
<blockquote>
<blockquote>
<ul>
<li>fstrings will GC and clear themselves from that table</li>
</ul>
</blockquote>
<p>I think this needs some work for the non-parser case, there seems to<br>
be a bad interaction with lazy sweep. My analysis of my failed<br>
patch for Feature <a class="issue tracker-2 status-5 priority-3 priority-lowest closed" title="string keys for hash literals should use fstrings (Closed)" href="https://bugs.ruby-lang.org/issues/8998">#8998</a>:<br>
<a href="http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net">http://mid.gmane.org/20131009021547.GA1839@dcvr.yhbt.net</a></p>
</blockquote>
<p>I don&#39;t doubt your analysis, but I don&#39;t think it&#39;s any worse with #freeze using fstring table. It&#39;s just multiplied by the number of strings that get frozen. Critical failure * N is still a critical failure.</p>
<blockquote>
<p>I also get (identical?) segfaults with the following:</p>
<p>diff --git a/object.c b/object.c<br>
--- a/object.c<br>
+++ b/object.c<br>
@@ -1029,6 +1029,8 @@ VALUE<br>
rb_obj_freeze(VALUE obj)<br>
{<br>
if (!OBJ_FROZEN(obj)) {<br>
+ if (TYPE(obj) == T_STRING)<br>
+ return rb_fstring(obj);<br>
OBJ_FREEZE(obj);<br>
if (SPECIAL_CONST_P(obj)) {<br>
if (!immediate_frozen_tbl) {</p>
</blockquote>
<p>Same argument here, I think.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424402013-10-14T08:40:23ZSam Saffronsam.saffron@gmail.com
<ul></ul><p>@hedius</p>
<p>There are 3 things being discussed here, I think it is fairly important we split them out.</p>
<ol>
<li>Parser optimisation for &quot;string&quot;.freeze</li>
<li>Unconditionally have #freeze return a pooled string</li>
<li>Change the semantics of #freeze so it amends the current object and operates like .NET / Java intern does. </li>
</ol>
<p>1) is completely doable with little side-effects. My caveat is that if #1 is the only thing done, the semantics for #freeze depend on the invocation. That said, this is minor. I totally accept that and prefer &quot;string&quot;.freeze to &quot;string&quot;f. </p>
<p>2) without 3) really scares me. </p>
<p>Imagine the odd semantics:</p>
<p>a = &quot;hello&quot;<br>
a.freeze # freezes one RVALUE in memory and returns a different RVALUE</p>
<p>As to 3) I don&#39;t think it can be implemented in MRI. If an RVALUE is moved in memory, MRI is going to have to crawl the heap and rewrite all the RVALUE that hold a ref to it, it does not keep track of this internally.</p>
<p>@charliesome thoughts? </p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424422013-10-14T12:53:27ZNobuyoshi Nakadanobu@ruby-lang.org
<ul></ul><p>(13/10/14 8:40), sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a> has been updated by sam.saffron (Sam Saffron).</p>
</blockquote>
<p>Thank you for summarizing.</p>
<blockquote>
<p>There are 3 things being discussed here, I think it is fairly important we split them out.</p>
<ol>
<li>Parser optimisation for &quot;string&quot;.freeze</li>
</ol>
<p>1) is completely doable with little side-effects. My caveat is that if #1 is the only thing done, the semantics for #freeze depend on the invocation. That said, this is minor. I totally accept that and prefer &quot;string&quot;.freeze to &quot;string&quot;f. </p>
</blockquote>
<p>It&#39;s a part of byte-code optimization, not parser. Since we have done<br>
it already for several methods, no problem there.</p>
<blockquote>
<ol>
<li>Unconditionally have #freeze return a pooled string</li>
<li>Change the semantics of #freeze so it amends the current object and operates like .NET / Java intern does.</li>
</ol>
<p>2) without 3) really scares me. </p>
<p>Imagine the odd semantics:</p>
<p>a = &quot;hello&quot;<br>
a.freeze # freezes one RVALUE in memory and returns a different RVALUE</p>
<p>As to 3) I don&#39;t think it can be implemented in MRI. If an RVALUE is moved in memory, MRI is going to have to crawl the heap and rewrite all the RVALUE that hold a ref to it, it does not keep track of this internally.</p>
</blockquote>
<p>Totally agree.</p>
<p>2+3 is wrong idea, I think.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424432013-10-14T15:59:43ZCharles Nutterheadius@headius.com
<ul></ul><p>Ok, let&#39;s just focus on #1 for now...</p>
<p>It seems like everyone agrees that &quot;string&quot;.freeze is a better choice than adding incompatible syntax now. That was the original proposal in this issue.</p>
<p>Should we remove &quot;string&quot;f on master and replace it with charliesome&#39;s patch for &quot;string&quot;.freeze? Or do we want to bikeshed a shorter name?</p>
<p>It occurred to me the there&#39;s already &quot;string&quot;.b which returns a binary string. Should we consider &quot;string&quot;.f which is similar to &quot;string&quot;f syntax but is just a normal method?</p>
<p>I think we&#39;re in agreement that we want the method format rather than the &quot;f&quot; suffix, so it&#39;s just a matter of deciding if we want a different method name for the new compiler-aware method.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424442013-10-14T17:23:19ZMatthew Kerwinmatthew@kerwin.net.au
<ul></ul><p>On Oct 14, 2013 5:00 PM, &quot;headius (Charles Nutter)&quot; <a href="mailto:headius@headius.com">headius@headius.com</a><br>
wrote:</p>
<blockquote>
<p>Ok, let&#39;s just focus on #1 for now...</p>
<p>It seems like everyone agrees that &quot;string&quot;.freeze is a better choice<br>
than adding incompatible syntax now. That was the original proposal in this<br>
issue.</p>
<p>Should we remove &quot;string&quot;f on master and replace it with charliesome&#39;s<br>
patch for &quot;string&quot;.freeze? Or do we want to bikeshed a shorter name?</p>
<p>It occurred to me the there&#39;s already &quot;string&quot;.b which returns a binary<br>
string. Should we consider &quot;string&quot;.f which is similar to &quot;string&quot;f syntax<br>
but is just a normal method?</p>
<p>I think we&#39;re in agreement that we want the method format rather than the<br>
&quot;f&quot; suffix, so it&#39;s just a matter of deciding if we want a different method<br>
name for the new compiler-aware method.</p>
</blockquote>
<p>Yes. I feel like regexen have suffixes because of decades of perl<br>
precedence, but they (suffixes) don&#39;t belong anywhere else.</p>
<p>For a method, I feel like #freeze is the better name, my only question is:<br>
is anyone monkeypatching it (and therefore will be bitten by this<br>
optimisation)? I doubt it, but we should still ask. The same question would<br>
have to be asked of the new method; I think there&#39;s more chance of #f being<br>
used in the wild than an overridden #freeze</p>
<p>Also in the favour of #freeze, it gives existing code a boost without any<br>
modification.</p>
<p>Sent from my phone, so excuse the typos.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424452013-10-14T17:29:18ZEric Wongnormalperson@yhbt.net
<ul></ul><p>Nobuyoshi Nakada <a href="mailto:nobu@ruby-lang.org">nobu@ruby-lang.org</a> wrote:</p>
<blockquote>
<p>(13/10/14 8:40), sam.saffron (Sam Saffron) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a> has been updated by sam.saffron (Sam Saffron).</p>
</blockquote>
<p>Thank you for summarizing.</p>
<blockquote>
<p>There are 3 things being discussed here, I think it is fairly important we split them out.</p>
<ol>
<li>Parser optimisation for &quot;string&quot;.freeze</li>
</ol>
<p>1) is completely doable with little side-effects. My caveat is that if #1 is the only thing done, the semantics for #freeze depend on the invocation. That said, this is minor. I totally accept that and prefer &quot;string&quot;.freeze to &quot;string&quot;f. </p>
</blockquote>
<p>It&#39;s a part of byte-code optimization, not parser. Since we have done<br>
it already for several methods, no problem there.</p>
</blockquote>
<p>So can we move this optimization to the parser instead? I think Sam means:</p>
<pre># optimized literal by parser. This may use pooled string since
# the string never existed in ObjectSpace before this line of code:
&quot;string&quot;.freeze
</pre>
<p>However, if .freeze operates on a variable (and not literal):</p>
<pre># leave this optimized by parser to avoid incompatibility
a = &quot;string&quot;
a.freeze =&gt; preserve existing behavior
</pre>
<blockquote>
<blockquote>
<ol>
<li>Unconditionally have #freeze return a pooled string</li>
<li>Change the semantics of #freeze so it amends the current object and operates like .NET / Java intern does.</li>
</ol>
<p>2) without 3) really scares me. </p>
<p>Imagine the odd semantics:</p>
<p>a = &quot;hello&quot;<br>
a.freeze # freezes one RVALUE in memory and returns a different RVALUE</p>
</blockquote>
</blockquote>
<p>Yes, this scares me if a.freeze made a different RVALUE</p>
<blockquote>
<blockquote>
<p>As to 3) I don&#39;t think it can be implemented in MRI. If an RVALUE is moved in memory, MRI is going to have to crawl the heap and rewrite all the RVALUE that hold a ref to it, it does not keep track of this internally.</p>
</blockquote>
<p>Totally agree.</p>
<p>2+3 is wrong idea, I think.</p>
</blockquote>
<p>Agreed.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424492013-10-14T23:46:32ZCharlie Somervillecharliesome@ruby-lang.org
<ul></ul><p>Totally agree with ssaffron on options 2 and 3 being scary. 3 is also impossible in MRI at the moment.</p>
<p>I&#39;m happy to commit my patch optimizing #freeze on a literal string if it looks good.</p>
<p>I think we should move the discussion of removing f-suffix and perhaps adding String#f to another ticket.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=424552013-10-15T07:57:30ZSam Saffronsam.saffron@gmail.com
<ul></ul><p>+1 for removing f suffix and amending the optimiser for #freeze </p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425462013-10-22T21:19:05ZCharles Nutterheadius@headius.com
<ul></ul><p>I have added <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Remove &quot;f&quot; suffix in favor of VM optimization of &quot;literal&quot;.freeze (Closed)" href="https://bugs.ruby-lang.org/issues/9042">#9042</a> and <a class="issue tracker-2 status-1 priority-4 priority-default" title="Add String#f method as shortcut for #freeze (Open)" href="https://bugs.ruby-lang.org/issues/9043">#9043</a> for removing the &quot;f&quot; suffix and adding the #f method, respectively.</p>
<p>I&#39;m starting to lean toward making #f be the only magic form, so nobody can complain that we&#39;re adding incompatible syntax (&quot;f&quot; suffix) or changing the semantics of an existing method (#freeze optimization).</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425542013-10-23T05:13:47ZCharlie Somervillecharliesome@ruby-lang.org
<ul></ul><blockquote>
<p>I&#39;m starting to lean toward making #f be the only magic form, so nobody can complain that we&#39;re ... changing the semantics of an existing method (#freeze optimization).</p>
</blockquote>
<p>I don&#39;t get this argument. Optimized String#freeze doesn&#39;t really change semantics in any real way. I&#39;m happy to just ignore anyone that complains about optimizing #freeze on a string literal.</p>
<p>There&#39;s only one way this could possibly affect any Ruby code - and that&#39;s if the code inspects the object_id of literal strings that it immediately calls #freeze on. I&#39;d say any code that breaks due to this was already fairly brittle anyway.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425652013-10-23T20:52:37ZBenoit Daloze
<ul></ul><p>I agree having optimized #freeze is better than #f.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425662013-10-23T21:23:17ZAkira Tanakaakr@fsij.org
<ul></ul><p>2013/10/8 headius (Charles Nutter) <a href="mailto:headius@headius.com">headius@headius.com</a>:</p>
<blockquote>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a>: Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix<br>
<a href="https://bugs.ruby-lang.org/issues/8992">https://bugs.ruby-lang.org/issues/8992</a></p>
</blockquote>
<p>Does anyone measure actual performance benefit?<br>
-- <br>
Tanaka Akira</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=425812013-10-24T02:23:18ZEric Wongnormalperson@yhbt.net
<ul></ul><p>Tanaka Akira <a href="mailto:akr@fsij.org">akr@fsij.org</a> wrote:</p>
<blockquote>
<p>2013/10/8 headius (Charles Nutter) <a href="mailto:headius@headius.com">headius@headius.com</a>:</p>
<blockquote>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a>: Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix<br>
<a href="https://bugs.ruby-lang.org/issues/8992">https://bugs.ruby-lang.org/issues/8992</a></p>
</blockquote>
<p>Does anyone measure actual performance benefit?</p>
</blockquote>
<p>Not directly, but I wasn&#39;t able to come up with performance benefits<br>
from my patch for <a href="https://bugs.ruby-lang.org/issues/8998">https://bugs.ruby-lang.org/issues/8998</a><br>
However, I don&#39;t have real apps which depend on hash/string-keys<br>
performance.</p>
<p>Perhaps other improvements (RGenGC) make it less useful.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427202013-11-02T11:23:20ZKoichi Sasada
<ul></ul><p>Matz, could you conclude this ticket?</p>
<p>I like this idea because:<br>
- No syntax change<br>
- Semantics was changed (&quot;literal&quot;.freeze.object_id =&gt; anytime same),<br>
but I can&#39;t imagine the apps which rely on this behavior.<br>
- Except 2nd point, this is no compatibility issue.</p>
<p>(2013/10/08 2:56), headius (Charles Nutter) wrote:</p>
<blockquote>
<p>Issue <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a> has been reported by headius (Charles Nutter).</p>
<hr>
<p>Feature <a class="issue tracker-2 status-5 priority-4 priority-default closed" title="Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix (Closed)" href="https://bugs.ruby-lang.org/issues/8992">#8992</a>: Use String#freeze and compiler tricks to replace &quot;str&quot;f suffix<br>
<a href="https://bugs.ruby-lang.org/issues/8992">https://bugs.ruby-lang.org/issues/8992</a></p>
</blockquote>
<p>-- <br>
// SASADA Koichi at atdot dot net</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427212013-11-02T11:59:59ZYukihiro Matsumotomatz@ruby-lang.org
<ul></ul><ul>
<li>I am OK with adding a new method (e.g. String#f) and compiler trick.</li>
<li>I hesitate a bit to change String#freeze semantics.</li>
<li>String#~ is very concise and in that sense attractive, but relation of &#39;~&#39; with patterns may cause confusion.</li>
</ul>
<p>So, my conclusion is adding String#f with compiler trick. I still need some discussion for changing String#freeze.<br>
Note that I don&#39;t have strong objection against String#freeze.</p>
<p>Matz.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427222013-11-02T12:18:46ZYusuke Endohmame@ruby-lang.org
<ul></ul><p>matz (Yukihiro Matsumoto) wrote:</p>
<blockquote>
<ul>
<li>I am OK with adding a new method (e.g. String#f) and compiler trick.</li>
</ul>
</blockquote>
<p>Somewhat oppose against &quot;f&quot; with compiler trick.</p>
<p>&quot;f&quot; is a typical meta-syntactic variable of functions.<br>
I guess some programs have the following code.</p>
<p>class String<br>
def f<br>
...<br>
end<br>
end</p>
<p>In fact, I&#39;ve found some instances in a few minutes:</p>
<p><a href="http://blog.goo.ne.jp/ruby-index/e/91995e39fe1fe72d339d882cf5ded055">http://blog.goo.ne.jp/ruby-index/e/91995e39fe1fe72d339d882cf5ded055</a><br>
<a href="http://python.g.hatena.ne.jp/mhrs/20060530">http://python.g.hatena.ne.jp/mhrs/20060530</a></p>
<h2></h2>
<p>Yusuke Endoh <a href="mailto:mame@tsg.ne.jp">mame@tsg.ne.jp</a></p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427242013-11-02T12:33:18ZCharlie Somervillecharliesome@ruby-lang.org
<ul></ul><p>Matz, I believe adding a new method will significantly limit the usefulness of this feature.</p>
<p>The reason optimizing &quot;&quot;.freeze is superior to a new syntax is that gems can start using this feature now without dropping support for versions &lt; 2.1.</p>
<p>I think many Gem authors will be very hesitant to monkey patch String#f to String#freeze.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=427342013-11-04T00:28:15ZBoris Stitnickyboris@iis.sinica.edu.tw
<ul></ul><p>@mame: Good catch. How about String#fz then?</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428082013-11-08T04:20:34ZCharles Nutterheadius@headius.com
<ul></ul><p>matz: Thank you for weighing in. I think we are on the same page.</p>
<p>There are a few different versions of this proposal getting tossed around, so I&#39;ll try to summarize the key points.</p>
<ol>
<li>We would like a compiler trick to replace the &quot;str&quot;f suffix.</li>
<li>The compiler trick would apply to literal strings with immediate calls to a freeze method and behave as &quot;str&quot;f does today.</li>
<li>The freeze method optimized by the compiler will be #freeze or a new shorter-named method #f or both.</li>
<li>Calls to #freeze against non-literals would behave as now.</li>
<li>Calls to #f, would use the fstring functionality to return a globally cached string (similar to interning in Java, from <a class="issue tracker-1 status-8 priority-4 priority-default closed" title="TestSignal#test_hup_me hangs up the test suite (Third Party&#39;s Issue)" href="https://bugs.ruby-lang.org/issues/8997">#8997</a>)</li>
</ol>
<p>It sounds like almost everyone is in favor of eliminating the &quot;str&quot;f suffix, so I think we can take that as written.</p>
<p>Decisions to make:</p>
<ol>
<li>Do we add a new method that can do <a class="issue tracker-2 status-2 priority-4 priority-default" title="String#frozen that takes advantage of the deduping (Assigned)" href="https://bugs.ruby-lang.org/issues/8977">#8977</a> behavior?
1a. What do we call it?</li>
<li>If we do not add a new method, should compiler tricks also optimize &quot;string&quot;.freeze?</li>
</ol>
<p>I think the following is a good plan:</p>
<ul>
<li>If we all agree that &quot;string&quot;f should go away, then we should switch to &quot;string&quot;.freeze compiler trick asap. @charliesome provided a patch.</li>
<li>If we want another method, we should decide on a name and decide whether &quot;string&quot;.freeze should still have compiler trick.</li>
</ul>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428302013-11-10T05:52:45ZCharlie Somervillecharliesome@ruby-lang.org
<ul></ul><p>At RubyConf Matz approved optimizing #freeze on static string literals and removing f-suffix.</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428322013-11-10T06:03:31ZBenoit Daloze
<ul></ul><p>charliesome (Charlie Somerville) wrote:</p>
<blockquote>
<p>At RubyConf Matz approved optimizing #freeze on static string literals and removing f-suffix.</p>
</blockquote>
<p>Great!</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=428872013-11-13T07:20:04ZCharles Nutterheadius@headius.com
<ul><li><strong>Status</strong> changed from <i>Open</i> to <i>Closed</i></li></ul><p>This has been completed as of revisions <a class="changeset" title="* compile.c (iseq_compile_each): emit opt_str_freeze if the #freeze method is called on a stati..." href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/43627">r43627</a> and <a class="changeset" title="parse.y: remove &quot;f&quot; suffix [Feature #9042] revert r42847 &quot;test_string.rb: add ..." href="https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/43634">r43634</a>.</p>
<p>Thanks for the collaboration, everyone :-)</p>
Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=435712013-12-10T19:54:14ZCharlie Somervillecharliesome@ruby-lang.org
<ul></ul><p>sawa: %-strings are already covered by #freeze optimization:</p>
<pre>λ ./miniruby --dump=insns -e &#39;%{}.freeze&#39;
== disasm: &lt;RubyVM::InstructionSequence:&lt;main&gt;@-e&gt;======================
0000 trace 1 ( 1)
0002 opt_str_freeze &quot;&quot;
0004 leave
</pre> Ruby trunk - Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffixhttps://bugs.ruby-lang.org/issues/8992?journal_id=435722013-12-10T19:55:31ZTsuyoshi Sawadasawadatsuyoshi@gmail.com
<ul></ul><p>charliesome (Charlie Somerville) wrote:</p>
<blockquote>
<p>sawa: %-strings are already covered by #freeze optimization:</p>
<pre>λ ./miniruby --dump=insns -e &#39;%{}.freeze&#39;
== disasm: &lt;RubyVM::InstructionSequence:&lt;main&gt;@-e&gt;======================
0000 trace 1 ( 1)
0002 opt_str_freeze &quot;&quot;
0004 leave
</pre></blockquote>
<p>Thanks. I should have checked before. I deleted my previous post.</p>