On Thu, Mar 20, 2014 at 10:59 PM, J Luis <[email protected]> wrote: > Well, ... thanks > > But "naive" question though. If we can do it with elaborate tricks, why > not just have a clean & simple way? >
The bottom line for whether something should be mutable or not is psychological: is the thing a value or a container? Integers are naturally immutable. If you modify an integer, you don't have the same integer with a different value, you have a different integer. If you have two distinct integers with the same value, they're not different, they're just different copies of the same integer. Arrays, on the other hand, are naturally mutable. If you have an array and you change the value in its first slot, you still have the same array, just with different contents. Similarly, you can have two different arrays that happen to contain the same values, but that doesn't make them the same array. So the question is whether a string is a value or a container. Julia isn't alone in the design choice to make strings immutable. Java made the same choice for various reasons<http://programmers.stackexchange.com/questions/195099/why-is-string-immutable-in-java>, as did Lisp, Scheme, Smalltalk, Python, Lua, Objective C, C#, and many other languages. In C, strings are just arrays of bytes, so mutability is quite natural. In higher level languages, however, strings are not containers, but rather values in their own right. This indicates that they should be immutable – "hello" and "hella" are simply different strings, no matter how you derived one from the other, just as 1+2im is a different complex number from 2+2im, even if you got the latter by adding 1 to the former. More concretely, mutable strings open you up to all kinds of nasty, hard-to-track-down bugs when you're not thinking of a string as a container of bytes. One of the worst bugs I ever had to find in Ruby was due to string mutability. Since Ruby treats strings as values, yet they are mutable, it's so easy to forget that doing str.gsub! deep in some subroutine will affect what every single caller sees. In this case, it modified an environment variable in place. Yikes. The bottom line is that languages that treat strings as first-class values and not just containers of bytes, strings should really be immutable. Currently, Julia isn't making great use of the immutability of Strings – under the hood, we use a mutable byte array. But we're going to change the way strings are represented in 0.4 to something quite different. Accordingly, if you are currently reaching under the hood of strings to mutate them, that code will break. Getting back to your original example, I would counter that you never really want to just do something like "replace the 16th character of this string" in isolation. How did you figure out the index 16? What you really want to do here is replace every instance of the NUL byte with a space. The replace function will do that for you: julia> s = "@GMTAPI@-000000\0 -R-10/0/35/45 -JM14c -Ba2 -P > lixo.ps" "@GMTAPI@-000000\0 -R-10/0/35/45 -JM14c -Ba2 -P > lixo.ps" julia> replace(s, '\0', ' ') "@GMTAPI@-000000 -R-10/0/35/45 -JM14c -Ba2 -P > lixo.ps" Only want to replace one NUL byte? Just use replace(s, '\0', ' ', 1) instead. Want to replace each NUL byte and any trailing whitespace with a single space? That's easy too: julia> replace(s, r"\0\s*", ' ') "@GMTAPI@-000000 -R-10/0/35/45 -JM14c -Ba2 -P > lixo.ps" So the fact that strings are immutable is compensated for by providing much more powerful tooling to manipulate string values.
