views:

209

answers:

1

It's the reverse of this question: http://stackoverflow.com/questions/93091/why-cant-strings-be-mutable-in-java-and-net

Was this choice made in Ruby only because operations (appends and such) are efficient on mutable strings, or was there some other reason?

(If it's only efficiency, that would seem peculiar, since the design of Ruby seems otherwise to not put a high premium on faciliating efficient implementation.)

+5  A: 

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.

rjh
OK. But why are strings mutable by default? I've edited the question and added "by default".
Seth Tisue
It's possible to make a string immutable by calling `.frozen` on it, but you can't really make an immutable string mutable - it would violate the principle. For example, if I pass an immutable string to a function, I wouldn't expect the function to make it mutable and start changing it.
rjh
It may also be because the ruby string is considered an enumerable.A string is seen as a "list" of characters, the natural expectation is that you can add and remove from a list. Implementing unmutable strings by default and still applying enumerable semantics would be painful.
Jean
@Jean, String is not enumerable in >= 1.9
banister
@banister : is it still mutable by default ? (I haven't played with ruby >1.8 yet, but I am surprised that it is not an enumerable anymore, that's a pretty big api change isn't it ? or is it just that it doesn't include Enumerable anymore but it still responds_to? most of the api ?)
Jean
@Jean, it's still mutable it just doesn't include Enumerable. THe main reason it's not enumerable is that a natural unit couldn't be decided upon. Iteration over lines or characters? for example.
banister
* should be `.freeze`, not .frozen :S
rjh
@banister: also, support for native encoding of strings. Do you enumerate over bytes, or characters? That's why we have `String#each_byte` and `String#each_char`.
rjh
@Jean: String isn't Enumerable because it's seen as a list of characters. If that were the case, it would be Enumerable by character, not by line as it is in 1.8.
sepp2k
I'm fascinated by the idea that immutability makes extra work for me as a programmer. My idea of extra work is that I have to be very careful who I show a string to, because anybody might mutate it! I **like** my immutable strings!
Norman Ramsey
@sepp2k it is both actually (each_byte) but I guess each line as default made more sense at the time ... @Norman maybe I was just traumatized by some uses of StringBuilder...
Jean
@Jean: Yes, you have each_byte, but all the Enumerable methods (map, select, inject) work on lines because each works on lines. So saying it's Enumerable by characters because it has each_byte (which is by bytes actually, not by characters, but that's tangential to the point) is a bit inaccurate I think, since each_byte has nothing to do with Enumerable.
sepp2k
@Norman: you should be very worried about passing hashes, arrays or objects to other functions then :)
rjh
@rjh: these days my psychiatrist is allowing me nothing but integers and floats---and she's not so sure about the floats.
Norman Ramsey
How exactly do immutable strings "make work harder for the programmer"?
cletus