Why did Matz choose to make Strings mutable by default in Ruby? Why did Matz choose to make Strings mutable by default in Ruby? ruby ruby

Why did Matz choose to make Strings mutable by default in Ruby?


This is in line with Ruby's design, as you note. Immutable strings are more efficient than mutable strings - less copying, as strings are re-used - but make work harder for the programmer. It is intuitive to see strings as mutable - you can concatenate them together. To deal with this, Java silently translates concatenation (via +) of two strings into the use of a StringBuffer object, and I'm sure there are other such hacks. Ruby chooses instead to make strings mutable by default at the expense of performance.

Ruby also has a number of destructive methods such as String#upcase! that rely on strings being mutable.

Another possible reason is that Ruby is inspired by Perl, and Perl happens to use mutable strings.

Ruby has Symbols and frozen Strings, both are immutable. As an added bonus, symbols are guaranteed to be unique per possible string value.


These are my opinions, not Matz's. For purposes of this answer, when I say that a language has "immutable strings", that means all its strings are immutable, i.e. there is no way to create a string that is mutable.

  1. The "immutable string" design sees strings as both identifiers (e.g. as hash keys and other VM-internal uses) and data-storage structures. The idea is that it's dangerous for identifiers to be mutable. To me, this sounds like a violation of single-responsibility. In Ruby, we have symbol for identifiers, so strings are free to act as data stores. It's true that Ruby allows strings as hash keys, but I think it's rare for a programmer to store a string into a variable, use it as a hash key, then modify the string. In the programmer's mind, there is (or should be) a separation of 2 usages of strings. Often times a string used as a hash key is a literal string, so there is little chance of it being mutated. Using a string as a hash key is not much different from using an array of two strings as a hash key. As long as your mind has a good grasp on what you're using as a key, then there's no problem.

  2. Having a string as a data-store is useful from a viewpoint of cognitive simplicity. Just consider Java and its StringBuffer. It's an extra data structure (in an already large and often unintuitive standard library) that you have to manage if you're trying to do string operations like inserting one string at a certain index of another string. So on the one hand, Java recognizes the need to do these kinds of operations, but because immutable strings are exposed to the programmer, they had to introduce another structure so the operations are still possible without making us reinvent the wheel. This puts extra cognitive load on the programmer.

  3. In Python, it seems like the easiest way to insert is to grab the substrings before and after the insertion-point, then concatenate them around the to-be-inserted string. I suppose they could easily add a method to the standard library that inserts and returns a new string. However, if the method is called insert, beginners may think it mutates the string; to be descriptive it would have to be called new_with_inserted or something odd like that. In everyday usage, "inserting" meaning you change the contents of the things inserted into (e.g. inserting an envelope into a mailbox changes the contents of the mailbox). Again, this raises the question, "why can't I change my data store?"

  4. Ruby provides freezing of objects, so they can be safely passed around without introducing subtle bugs. The nice thing is that Ruby treats strings just like any other data structure (arrays, hashes, class instances); they can all be frozen. Consistency is programmer-friendly. Immutable strings make strings stand out as a "special" data structure, when it's not really, if you use it as a data store.