so what exactly is const supposed to mean?

kris foo at bar.com
Mon Jul 3 13:20:49 PDT 2006


Chris Nicholson-Sauls wrote:
> Technically no.  Although at present, there are precisely two possible 
> methods, and both require wrapping every single field up with a D-style 
> property.  (True properties could actually have the potential to make 
> this simpler... but we don't have those either.)
> 
> Method #1 - Write the class as innately immutable, then write a mutable 
> subclass.  This is the methodology at work in Mango, for example, where 
> the module mango.io.FilePath actually defines two classes, 
> FilePath:Object and MutableFilePath:FilePath.
> 
> Method #2 - Same as above, but with one class that has a pair of methods 
> (mutable() and immutable() for example) that activate/deactivate 
> mutability, usually locking on something such as instance of another 
> class (the identity of which doesn't particularly matter). For 
> (quick'n'dirty) example:

Method #3 - each mutator function/method actually creates a clone of the 
original, mutates it, and returns that instead.

Method #1 & #2 are typically the most efficient, but can expose an 
achilles heel. For instance, suppose you had an immutable String class? 
At some point, it will need to expose the content therein -- perhaps via 
a toString() method, or perhaps something more subtle? At that point, 
the class either returns a .dup of the internal content, or it exposes 
the internal content directly by returning it (as an array). Neither of 
these options are entirely attractive, and it's the reason why fully 
immutable classes/structs are not entirely practical in D at this time.

This "return value" concern is also the reason why I believe that a 
"minimalist" support for "read-only" would be to protect just the return 
values. With the latter, one could happily return internal aggregate 
content (as arrays) and be safe in the knowledge that the compiler will 
catch pedestrian errors. However, I'd much rather see const-by-default 
instead -- that's a more practical solution, and should offer notable 
opportunities for optimization.

One should note that the goal of such mechanisms is to tighten up the 
"contract" between caller and callee. This becomes increasingly 
important within multithreaded designs, to the point of becoming a 
fundamental requirement in some ways (in terms of robustness, 
simplicitly, efficiency, deterministic behaviour, etc). CoW is another 
mechansism intended to achieve similar results, but the key distinction 
is the lack of an enforceable contract. With mutable/immutable decls, 
the compiler has the necessary information to catch cases where the 
contract is being broken. With CoW, the compiler does not have that meta 
information available (whether the design says it's OK to alias or not).

Of course, this won't stop some determined fool from bypassing the 
contract altogether: even with immutable-by-default, one could 
presumably cast() lvalues in some manner to subvert the contract. But 
that's not the point -- the compiler would be looking to catch honest 
mistakes, and not trying to cure stupidity :p

Hope this helps.



More information about the Digitalmars-d-learn mailing list