Closed keleshev closed 9 years ago
Hi @keleshev,
Strings in Crystal are already immutable, like in Java and C#.
About arrays and maps being immutable by default, how would that work? What about other types, will they still be mutable? How to implement all of this in an efficient way? Will push
and pop
disappear from the language? I think if we make this change we will end up with a completely different language, maybe Haskell or Erlang.
I like this article from John Carmack.
In short, I like immutability, but I don't think making it the default in a language, solves anything.
I think if we make this change we will end up with a completely different language, maybe Haskell or Erlang.
Scala has collection.mutable
and collection.immutable
. Though they're terribly implemented (because they tried to reuse classes they shouldn't have)
Note that I'm not against having immutable collections. I'm against having them be the default.
There's no "default" in scala :)
Clojure's collections are immutable by default and efficient. As far as I remember Rich Hickey talks about some details of datastructures here: https://www.youtube.com/watch?v=wASCH_gPnDw And as far know this book describes efficient purely-functional data structures in depth: http://www.amazon.com/Purely-Functional-Structures-Chris-Okasaki/dp/0521663504/ref=sr_1_1?ie=UTF8&qid=1419876757&sr=8-1&keywords=purely+functional+data+structures
I googled for Clojure vectors and this pops out: http://hypirion.com/musings/understanding-persistent-vector-pt-1. Based on the graphs I see there it seems that it should be a decent explanation.
@keleshev Thanks, I'll watch those links soon :-)
But if you want immutable collections by default then you want to use another language. I mean, this is valid Ruby/Crystal code:
a = [1, 2, 3]
a << 4
elem = a.shift
puts elem #=> 1
puts a #=> [2, 3, 4]
Now with immutable collections this would be something like this:
a = [1, 2, 3]
a = a << 4
elem, a = a.shift
puts elem #=> 1
puts a #=> [2, 3, 4]
That is, each operation can't mutate the original array so you must assign every operation to a new variable. In the case of shift
a tuple must be returned: the shifted element and the resulting array. So tedious! But maybe for doing this it would be nice to have some kind of pattern matching on arrays? Some more steps and we end up with Haskell, Erlang, Elixir, or some other functional language.
I'd also like to see benchmarks of algorithms implemented with purely immutable collections vs. with mutable collections. If you can provide some of those algorithms in a functional language I will happily translate them to Crystal and do the performance comparison. Havlak would be a good benchmark to try this (but it's maybe too long.)
As other said, we can have immutable collections in the standard library. I just don't think having them be the default (that is, when you use the []
and {}
literals) is going to happen.
Having immutable structures right into Crystal would allow the compiler to optimize the generated code (maybe) and lint the code, since it would know that the data won't change.
A gem like arel, for example, that returns a new object on every operation, would greatly benefit from immutability. The same for chained operations on collections that do not alter it (eg: filter, map, reduce). Not having pop/push or slow versions of them isn't a problem, as long as we can quickly initialize the collection with a fixed number of elements (for instance).
But, yeah, not be the default —I don't want another language, there is already Rust, among others.
We can always have an inmmutable datastructures
library if you want to.
So I'll close this.
I also think that having immutable collections as default would imply a far too drastic change for Crystal, but I really like the idea of having immutable collections in the standard library.
This shard: https://github.com/lucaong/immutable could be a fine starting point.
Moreover, something easier than Immutable::Vector[1, 2, 3, 4, 5]
to define immutable structures would be welcome, perhaps a method call or a sufix, like this:
[1, 2, 3, 4, 5].to_im
[1, 2, 3, 4, 5]_im
It is possible to add [1, 2, 3, 4, 5].to_im
method to a shard, it doesn't require changes to language or stdlib.
I was wondering, what is your take on mutability vs. immutability for Crystal? Do you think it would be sensible to default to immutable strings, arrays and maps?