Immutability and other attributes, please review

Jonathan M Davis jmdavisProg at gmx.com
Thu Jun 14 04:11:42 PDT 2012


On Thursday, June 14, 2012 12:31:16 Roman D. Boiko wrote:
> On Thursday, 14 June 2012 at 09:56:08 UTC, Roman D. Boiko wrote:
> > By the way, the whole data model is designed to be immutable.
> > Should I replace const with immutable then?
> 
> The other thing I don't like is having to cast everywhere:
> 
> struct Maybe(T)
> {
>    immutable T* payload; // pointer to data
>    pure nothrow this(T* payload)
>    {
>      this.payload = cast(immutable) payload;
>    }
>    pure nothrow @property T front() const in{ assert(!empty); }
>    body{ return cast(T) *payload; }
>    //...
> }
> 
> OTOH, I'm not sure making input parameter immutable would be
> better for the user, same for function return type.

I haven't had the chance to look over your code yet, but this looks 
_seriously_ suspect. Casting to and from immutable or cast away const are 
things that should be done _very_ rarely. One of the few times that casting to 
immutable makes any sense is when you need an object to be mutable while you 
put it together and then immutable afterwards. But when you do that, that 
reference or pointer is the _only_ reference to that data. e.g.

auto func(size_t numElems)
{
    auto arr = new int[](numElems);

    foreach(ref e; arr)
      //do something to initialize e

    return cast(immutable int[])arr;
}

Taking a function's parameter (which came from who-knows-where) and casting it 
to immutable is almost certainly a terrible thing to do. If there are _any_ 
other references to that data, you will have bugs. immutable is supposed to 
guarantee that the data is _never_ altered. So, when you cast something to 
immutable, you're telling the compiler that it's okay to treat that data as 
immutable and that you will _not_ have any mutable references to that data or 
alter it in any way. If you do, you'll be breaking the compiler's guarantees.

Ideally, you would always construct immutable objects as immutable rather than 
creating them as mutable and then casting them to immutable, but that's not 
always possible.

And taking your payload, which is immutable, and casting away immutable when 
you return it from front is truly bad. Casting away const or immutable and 
then mutating that object is _undefined_ behavior. Do _not_ do it unless you 
have to and know what you're doing.

These stackoverflow questions may help you understand better:

http://stackoverflow.com/questions/4219600/logical-const-in-d
http://stackoverflow.com/questions/10364837/why-do-i-have-to-cast-this

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list