Preferences

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.

Even in C, string literals are immutable, and mutating them is undefined behavior.
But in the syntax of scripting language its very easy to create a new string from the old string, destroy old string, replace variable by new string. Which appears mutable from the point of view of the developer
Can't you do the exact same in compiled languages e.g. C or Rust?
You can, but allocating and deallocating is more tedious without a GC, and if you care about performance, you might want to have mutable strings.
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.
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

    '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.)
Cuis.

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

    true .
Amongst the lisps, AutoLISP had the one standout feature that was immutable strings by default. Many other lisps wished they could have that too, esp. for the GC.
All strings in python are immutable, as an example.
Also JavaScript.
Java too. Rust has only 99 string types, some of those are immutable also.
It does not really matter in rust anyway: literals are &’static str so naturally immutable and essentially free, and mutable strings require jumping hoops to share, so it’s hard to unwittingly have one mutate from under you.
Rust the language has one string type: &str

The standard library also has String, CString, CStr, OsString, and OsStr.

The latter four are for niche situations. 99.9% of the time, it's similar to Java: &str is Java's String, String is Java's StringBuffer/StringBuilder.

There is also &mut str. The nice thing about Rust is that the same memory area can be used as a "StringBuilder" with &mut str, and then as a "String" with &str. Once you have a &str reference, Rust statically guarantees that no one else cam mutate it.
99.9% of the time rust has 1 string type. The other 0.1% of the time it has 99, got it.
It has two, not 99, with owned and borrowed pairs.
I would add Path and PathBuf to that list.
Rust has one core String type.

  String

  &str

  &mut str

  &'static str 

  etc. 
These are just the language semantics.

The other string types are non-Rust strings. Filesystem, C strings, etc. You only deal with them in dealing with specific OS and binding interfaces.

95% of the time you'll just be using String.

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.
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.
> for a web-focused scripting language it makes sense to default to mutable strings

Why do you say that? I would say the opposite.

Because there’ll likely be a lot of string concatenation in a language whose job is to output HTML. Adding a single char to a 1k string will require allocating a modified copy, in mutable strings it’s just appending in a preallocated buffer.
If you are using string concatenation to build HTML in your application layer, you are fundamentally doing it wrong.

Ruby isn’t making all strings immutable here. Just string literals. You are free to allocate mutable strings that can be appended to, to your heart’s content. It is extremely rare that modifying a literal is intended behavior, since their contents are permanently persisted throughout the lifetime of your program. With your example, this would be like having one shared global buffer for your final document.

> for a web-focused scripting language

Ruby is not a web focused scripting language.

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".

Exactly thank you. Not sure why you’re downvoted
Mutable strings were part of the perl heritage, which was one of the direct ancestors for ruby.

This item has no comments currently.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal