Live data from Hacker News

Ruby 3.4 frozen string literals: What Rails developers need to know

prateekcodes.dev

121–130 of 131 posts

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#121
post #5

Earlier quoted context omitted.

I would actually say it’s the opposite in this case: it’s extremely common in scripting languages for strings to be immutable, mutable strings are usually only available in lower level languages. I’m very surprised Ruby had this feature at all.

Common Lisp and Smalltalk have mutable strings, I think. So it’s not too surprising that ruby does too, since it was pretty heavily influenced by these languages.

Specifically, it's non-literal strings that are mutable. Implementations of either may allow you to modify the literals, but it's likely to break something due to interning. The Common Lisp standard is clear that destructive literal modification is undefined behavior. I believe it's the same in Smalltalk, and I remember you were admonished to never use the direct modification messages (like at:put: or replaceFrom:to:with:) on strings without copying them first.

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#122
post #121

Earlier quoted context omitted.

Common Lisp and Smalltalk have mutable strings, I think. So it’s not too surprising that ruby does too, since it was pretty heavily influenced by these languages.

Specifically, it's non-literal strings that are mutable. Implementations of either may allow you to modify the literals, but it's likely to break something due to interning. The Common Lisp standard is clear that destructive literal modification is undefined behavior. I believe it's the same in Smalltalk, and I remember you were admonished to never use the direct modification messages (like at:put: or replaceFrom:to:…

I looked around and it seems like Smalltalk didn't make modifying literals UB, the way Common Lisp does but I'm not an expert. Still, for both languages, most implementations won't stop you if you modify string literals, you just have to deal with the consequences.

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#123
post #5

Earlier quoted context omitted.

I would actually say it’s the opposite in this case: it’s extremely common in scripting languages for strings to be immutable, mutable strings are usually only available in lower level languages. I’m very surprised Ruby had this feature at all.

It’s true that many languages have immutable strings, but for a web-focused scripting language it makes sense to default to mutable strings. I think the comment is about that you now need to choose mutable vs immutable, and that is framed as a consequence of broader adoption. Which is a development I have also seen before.

Ruby is a web-focused scripting language in the same sense that Python is an AI-focused scripting language.

JavaScript is much more of a "web-focused scripting language" than Ruby is, and it is quite happy with immutable strings (only).

> I think the comment is about that you now need to choose mutable vs immutable, and that is framed as a consequence of broader adoption.

Ruby has also had immutable (frozen) strings for a very long time, so you've always had the choice. What is changing is that string literals are (eventually) going to migrate from "mutable with a strong-encouraged file level switch to make them immutable" to "immutable".

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#124
post #83

Earlier quoted context omitted.

That's not quite how Ruby and similar languages like Python or JS work. Variables don't "contain" a string, they just point to objects on the heap. So: my_string = same_string = "Hello World" Here both variables are essentially pointers to a pre-existing object on the heap, and that object is immutable.

Yeah it’s just the naming is weird. The string literal is not the object on the heap, it’s part of the program’s code itself, which was (assumedly) never mutable to begin with.

"Frozen string literals" doesn't mean that string literals are frozen, but that string literals (in the code) are reified as frozen strings. Obviously, the feature name is less fully expressive than the full sentence used to explain it, but that's a natural trade-off with wanting a usable name; it is evocative of the definition, not a restatement of it.

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#125
post #121

Earlier quoted context omitted.

Common Lisp and Smalltalk have mutable strings, I think. So it’s not too surprising that ruby does too, since it was pretty heavily influenced by these languages.

Specifically, it's non-literal strings that are mutable. Implementations of either may allow you to modify the literals, but it's likely to break something due to interning. The Common Lisp standard is clear that destructive literal modification is undefined behavior. I believe it's the same in Smalltalk, and I remember you were admonished to never use the direct modification messages (like at:put: or replaceFrom:to:…

    'justastring' at: 6 put: $S; yourself

    'justaString' .

However

    #'justasymbol' at: 6 put: $S; yourself

    errorNoModification
        self error:  'symbols can not be modified.'

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#126
post #125
post #121

Earlier quoted context omitted.

Specifically, it's non-literal strings that are mutable. Implementations of either may allow you to modify the literals, but it's likely to break something due to interning. The Common Lisp standard is clear that destructive literal modification is undefined behavior. I believe it's the same in Smalltalk, and I remember you were admonished to never use the direct modification messages (like at:put: or replaceFrom:to:…

'justastring' at: 6 put: $S; yourself 'justaString' . However #'justasymbol' at: 6 put: $S; yourself errorNoModification self error: 'symbols can not be modified.'

> 'justastring' at: 6 put: $S; yourself

Evaluating this yields an error in both Squeak and Pharo. What Smalltalk are you using? I'm going to guess Cuis, in which case your example holds, but is misleading. Consider:

    a:='justastring'.
    b:='justastring'.
    a at: 6 put: $S.
    a, ' = ', b.
    'justaString = justaString' .
Notice, modifying "a" also modified "b," because of the shared literal frame entry. This is why you were traditionally admonished to avoid directly modifying string literals. (Which wasn't an issue given the design of the string classes, and the general poor manners of destructively modifying a string argument of unknown origin.)

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#127

Earlier quoted context omitted.

Mutable strings can be duplicated too. You can use reference counting, or borrow checking in Rust.

Mutable string literals can't be easily deduplicated, unless your language semantics are that a literal is a singleton and all mutations are visible by all other evaluations of that literal. But no sane language would do that.

If the strings are backed by reference counted buffers, you can use copy-on-write semantics to provide the API of a mutable string but share buffers when a string is copied. Most C++ standard libraries actually did this prior to the multicore era.

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#128
post #121

Earlier quoted context omitted.

Specifically, it's non-literal strings that are mutable. Implementations of either may allow you to modify the literals, but it's likely to break something due to interning. The Common Lisp standard is clear that destructive literal modification is undefined behavior. I believe it's the same in Smalltalk, and I remember you were admonished to never use the direct modification messages (like at:put: or replaceFrom:to:…

I looked around and it seems like Smalltalk didn't make modifying literals UB, the way Common Lisp does but I'm not an expert. Still, for both languages, most implementations won't stop you if you modify string literals, you just have to deal with the consequences.

I'm too lazy to review the ANSI spec, but the Smalltalk Bluebook VM served as a reference implementation for Smalltalk VMs for years, and it used a method-scoped literal frame for string (and other) literals:

> The selectors in parentheses may be replaced with other selectors by modifying the compiler and recompiling all methods in the system. The other selectors are built into the virtual machine.

> Any objects referred to in a CompiledMethod's bytecodes that do not fall into one of the categories above must appear in its literal frame. The objects ordinarily contained in a literal frame are

> shared variables (global, class, and pool)

> most literal constants (numbers, characters, strings, arrays, and symbols)

> most message selectors (those that are not special)

> Objects of these three types may be intermixed in the literal frame. If an object in the literal frame is referenced twice in the same method, it need only appear in the literal frame once. The two bytecodes that refer to the object will refer to the same location in the literal frame.

> Two types of object that were referred to above, temporary variables and shared variables, have not been used in the example methods. The following example method for Rectangle merge: uses both types. The merge: message is used to find a Rectangle that includes the areas in both the receiver and the argument.

http://www.mirandabanda.org/bluebook/bluebook_chapter26.html

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#129

Earlier quoted context omitted.

All of those languages except JavaScript have mutable strings; they just have different names and API shapes. Python has io.StringIO, Java has StringBuilder, Rust has String. (JavaScript has less need for this because JavaScript strings are ropes in most widely used implementations, reducing the overhead of concatenation, though the language spec doesn't require this.)

By your incredible criteria of things being mutable strings if they behave nothing like strings but can produce one, JavaScript absolutely does have a mutable string, it’s called Array. It’s also a mutable integer.

I don't consider JavaScript's Array to count because using it as a mutable string incurs a significant amount of additional overhead, because it has to box every character and check at runtime the type of each element. This is not true of the APIs that I listed.

Re: Ruby 3.4 frozen string literals: What Rails developers need to know

#130
post #126
post #125

Earlier quoted context omitted.

'justastring' at: 6 put: $S; yourself 'justaString' . However #'justasymbol' at: 6 put: $S; yourself errorNoModification self error: 'symbols can not be modified.'

> 'justastring' at: 6 put: $S; yourself Evaluating this yields an error in both Squeak and Pharo. What Smalltalk are you using? I'm going to guess Cuis, in which case your example holds, but is misleading. Consider: a:='justastring'. b:='justastring'. a at: 6 put: $S. a, ' = ', b. 'justaString = justaString' . Notice, modifying "a" also modified "b," because of the shared literal frame entry. This is why you were tra…

Cuis.

    | a b |
    a := 'justastring'.
    b := 'justastring'.
    a == b

    true .
Post reply on HN