From: eregontp@... Date: 2019-09-29T22:08:15+00:00 Subject: [ruby-core:95152] [Ruby master Feature#16150] Add a way to request a frozen string from to_s Issue #16150 has been updated by Eregon (Benoit Daloze). I'll get to the point because I think we're starting to discuss unrelated things in this issue. headius (Charles Nutter) wrote: > I'd argue it's actually NEVER safe to modify the result of calling `to_s` [...] Yes, and it has never been. `String#to_s` has always returned itself, including for frozen strings, so of course `to_s` means "convert to a String if you're not already" and gives no guarantee to return a new String ready to be mutated. It is the same for all other `to_*` methods, isn't it? I think this is already well understood by Rubyists, and the changes for Symbol#to_s, Module#name, true/false/nil.to_s just make an existing behavior a bit more common. So, I think there is nothing to change about `String#to_s`, except maybe improving the documentation of `Kernel#to_s` in general. > I know this is a difficult pill to swallow. The original purpose of this issue was to consider adding a way to *request* frozen strings from to_s, since that would at least be an opt-in. Hence the suggestions of a to_z or similar new mechanism. I think there is no need for yet another "convert to String" method. We changed the methods that used to allocate on every call instead of returning an internal frozen String (I don't think there are others, are there?). Making String#to_s not return `self` is just worse for allocations, and would be inconsistent with other `to_*` methods. Is there any advantage to make String#to_s not return `self`? > * A way to explicitly request a frozen string from any object, such as `to_z`, so code could start migrating toward frozen strings today. Why are `String#-@` and `str.dup.freeze` not enough? > * A pragma to explicitly set a file as having mutable-string-literal, as a local escape hatch for future default frozen-string-literal. > * A command-line flag to force mutable-string-literal when no pragma exists, as a global escape hatch for future default frozen-string-literal. That's about frozen string literals, #11473, please comment there, I don't think we should mix both issues. In fact, I think this issue is done and is already correctly closed. We addressed the cases that were allocating too much, without the need for a new method for converting to strings. ---------------------------------------- Feature #16150: Add a way to request a frozen string from to_s https://bugs.ruby-lang.org/issues/16150#change-81793 * Author: headius (Charles Nutter) * Status: Closed * Priority: Normal * Assignee: Eregon (Benoit Daloze) * Target version: ---------------------------------------- Much of the time when a user calls to_s, they are just looking for a simple string representation to display or to interpolate into another string. In my brief exploration, the result of to_s is rarely mutated directly. It seems that we could save a lot of objects by providing a way to explicitly request a *frozen* string. For purposes of discussion I will call this to_frozen_string, which is a terrible name. This would reduce string allocations dramatically when applied to many common to_s calls: * Symbol#to_frozen_string could always return the same cached String representation. This method is *heavily* used by almost all Ruby code that intermingles Symbols and Strings. * nil, true, false, and any other singleton values in the system could similarly cache and return the same String object. * The strings coming from core types could also be in the fstring cache and deduplicated as a result. * User-provided to_s implementations could opt-in to caching and returning the same frozen String object when the author knows that the result will always be the same. A few ideas for what to call this: * `to_fstring` or `fstring` reflects internal the "fstring" cache but is perhaps not obvious for most users. * `to_s(frozen: true)` is clean but there will be many cases when the kwargs hash doesn't get eliminated, making matters worse. * `def to_s(frozen = false)` would be mostly free but may not be compatible with existing to_s params (like `Integer#to_s(radix)` This idea was inspired by @schneems's talk at RubyConf Thailand, where he showed significant overhead in ActiveRecord from Symbol#to_s allocation. -- https://bugs.ruby-lang.org/ Unsubscribe: