Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't scala have C++-like const-semantics?

In C++. I can declare most things as const, for example:
Variables: const int i=5;
Scala has val i=5, however this will only prevent reassigning, not changing the object as the following exampe shows:
C++:

const int i[]={1,2,3,4};
i[2]=5; //error
Scala:
val a=Array(1,2,3,4)
a(2)=5 //a is now Array(1, 2, 5, 4)

It gets even worse with member functions:
C++:

class Foo {
int i;
int iPlusFive() const {return i+5;}
int incrementI(){ return ++i; }
}
I can be sure, that calling iPlusFive won't change the object and that I won't accidentally call incrementI on a const object.

When it comes to collections, C++ continues it's const-correct streak with const collections: simply declare your vector as const and you can't change it. Assign a non-const vector<Int> to a const vector<Int> and the compiler won't copy anything and will prevent you from changing anything in the now const collection.

Scala has scala.collection.mutable.whatever and scala.collection.immutable.whatever, you can't just convert mutable collections to immutable collections, furthermore you're still allowed to change the collected objects with their non-const member functions.

Why does scala, which has an otherwise really great type-system, not have anything comparable to C++ const-keyword?

Edit: Margus suggested using import scala.collection.mutable. My solution was to use

import scala.collection.mutable.HashMap
import scala.collection.immutable.{HashMap => ConstHashMap}
This will make the mutable HashMap available as HashMap and the immutable als ConstHashMap, however I still like the C++ approach better.
like image 701
tstenner Avatar asked Oct 05 '10 10:10

tstenner


2 Answers

The thing I dislike about C++ const logic is that it is about the reference and not about the object that is referenced. If I have a "const T *" there is no guarantee that someone holding a non-const pointer will not modify the state of the object. As such, it does not help in any way to avoid race conditions in multi-threaded systems nor does it help in implementing persistent containers.

In my opinion it is very helpful to have a concept of immutable classes and lack of immutable containers in a standard library is a mistake in any language. Since these should exhibit observable immutability but will likely need to be able to change internal/invisible state for efficiency reasons I think const-syntax would be of little help.

Scala has the immutable classes we need to either use directly or base other immutable classes on. That is extremely valuable. Additional syntax might be a nice addition but I can live without it.

like image 135
Silvio Bierman Avatar answered Sep 20 '22 22:09

Silvio Bierman


Because C++ const is not that great in complex systems.

I can be sure, that calling iPlusFive won't change the object and that I won't accidentally call incrementI on a const object.

No, you can't, because the implementation (which may be in a library somewhere out of sight) can cast the constness away. Without const, other languages have to enforce the immutability in safer ways (see Collections.unmodifiableList() in @Margus's answer, for instance).

Const is just documentation that the compiler reads. Documentation is usually helpful but sometimes misleading.

When it comes to collections, C++ continues it's const-correct streak with const collections: simply declare your vector as const and you can't change it.

Aggregation is where const often breaks down for me. I often want to declare, for instance, that a method will not change the vector but may change a member of it (or return a non-const member reference). I have to make it all const or all nonconst or invent new type variations for every combination.

'mutable' makes up for some of the aggregation issues but introduces more complexity and misuse.

like image 43
xan Avatar answered Sep 19 '22 22:09

xan