From: "headius (Charles Nutter)" Date: 2013-11-08T04:20:35+09:00 Subject: [ruby-core:58225] [ruby-trunk - Feature #8992] Use String#freeze and compiler tricks to replace "str"f suffix Issue #8992 has been updated by headius (Charles Nutter). matz: Thank you for weighing in. I think we are on the same page. There are a few different versions of this proposal getting tossed around, so I'll try to summarize the key points. 1. We would like a compiler trick to replace the "str"f suffix. 2. The compiler trick would apply to literal strings with immediate calls to a freeze method and behave as "str"f does today. 3. The freeze method optimized by the compiler will be #freeze or a new shorter-named method #f or both. 4. Calls to #freeze against non-literals would behave as now. 5. Calls to #f, would use the fstring functionality to return a globally cached string (similar to interning in Java, from #8997) It sounds like almost everyone is in favor of eliminating the "str"f suffix, so I think we can take that as written. Decisions to make: 1. Do we add a new method that can do #8977 behavior? 1a. What do we call it? 2. If we do not add a new method, should compiler tricks also optimize "string".freeze? I think the following is a good plan: * If we all agree that "string"f should go away, then we should switch to "string".freeze compiler trick asap. @charliesome provided a patch. * If we want another method, we should decide on a name and decide whether "string".freeze should still have compiler trick. ---------------------------------------- Feature #8992: Use String#freeze and compiler tricks to replace "str"f suffix https://bugs.ruby-lang.org/issues/8992#change-42808 Author: headius (Charles Nutter) Status: Open Priority: Normal Assignee: matz (Yukihiro Matsumoto) Category: core Target version: current: 2.1.0 BACKGROUND: In https://bugs.ruby-lang.org/issues/8579 @charliesome introduced the "f" suffix for creating already-frozen strings. A string like "str"f would have the following characteristics: * It would be frozen before the expression returned * It would be the same object everywhere, pulling from a global "fstring" table To avoid memory leaks, these pooled strings would remove themselves from the "fstring" table on GC. However, there are problems with this new syntax: * It will never parse in Ruby 2.0 and earlier. * It's not particularly attractive, though this is a subjective matter. * It does not lend itself well to use in other scenarios, such as for arrays and hashes (http://bugs.ruby-lang.org/issues/8909 ) PROPOSAL: I propose that we eliminate the new "f" suffix and just make the compiler smart enough to see literal strings with .frozen the same way. So this code: str = "mystring".freeze Would be equivalent in the compiler to this code: str = "mystring"f And the fstring table would still be used to return pooled instances. IMPLEMENTATION NOTES: The fstring table already exists on master and would be used for these pooled strings. An open question is whether the compiler should forever optimize "str".frozen to return the pooled version or whether it should check (inline-cache style) whether String#freeze has been replaced. I am ok with either, but the best potential comes from ignoring String#freeze redefinitions...or making it impossible to redefine String#freeze. BONUS BIKESHEDDING: If we do not want to overload the existing .freeze method in this way, we could follow suggestions in http://bugs.ruby-lang.org/issues/8977 to add a new "frozen" method (or some other name) that the compiler would understand. If it were "frozen", the following two lines would be equivalent: str = "mystring".frozen str = "mystring"f In addition, using .frozen on any string would put it in the fstring table and return that pooled version. I also propose one alternative method name: the unary ~ operator. There is no ~ on String right now, and it has no meaning for strings that we'd be overriding. So the following two lines would be equivalent: str = ~"mystring" str = "mystring"f JUSTIFICATION: Making the compiler aware of normal method-based String freezing has the following advantages: * It will parse in all versions of Ruby. * It will be equivalent in all versions of Ruby other than the fstring pooling. * It extends neatly to Array and Hash; the compiler can see Array or Hash with literal elements and return the same object. * It does not require a pragma (http://bugs.ruby-lang.org/issues/8976 ) * It looks like Ruby. -- http://bugs.ruby-lang.org/