immutable, const, enum

Steven Schveighoffer schveiguy at yahoo.com
Tue Apr 28 12:03:39 PDT 2009


On Tue, 28 Apr 2009 13:43:48 -0400, bearophile <bearophileHUGS at lycos.com>  
wrote:

>> The const and immutable function attributes can also appear after the  
>> closing parenthesis of the parameter list: <
>
> I think this doesn't produce much damage, but why?

First, C++ does it this way:

int foo() const
{
}

Second, because const/immutable is a type constructor, it can be applied  
to the return type as well as the function.  So what looks less confusing  
to you:

const A foo() // const function which returns a mutable A
A foo() const // same thing, clearly const can't apply to A

const const A foo() // const function which returns a const A
const A foo() const // ditto

There have been proposals to change const to const(this), so it is clear  
what you are applying const to (in fact, that is what a const function  
does, just mark the hidden "this" parameter as const):

const(this) A foo()
const A foo() // would either be syntax error or mean a normal fn that  
returns a const A

I'd be in favor of such a change.

> -----------------
>
> The following things are written about constview/immutable member  
> functions:
>
> immutable member functions are guaranteed that the object and anything  
> referred to by the this reference is immutable. They are declared as:
>
> struct S {
>     int x;
>
>     immutable void foo() {
>         x = 4;	    // error, x is immutable
>         this.x = 4; // error, x is immutable
>     }
> }
>
> constview member functions are functions that are not allowed to change  
> any part of the object through the member function's this reference.
>
> I don't understand such explanations, and I'd like to see a bit wider  
> example(s) about it.

The detail you are missing is that anything is implicitly castable to  
const, but nothing else implicitly casts.

Think about it this way:  const means "I cannot change this, but something  
else might be able to."  So mutable can implicitly be cast to const if I  
don't want to change it, and immutable can implicitly cast to const.   
Mutable and immutable cannot implicitly be cast to eachother because that  
would violate immutability.  So since something that is const could  
potentially be immutable OR mutable, it can't be implicitly cast to  
immutable or mutable because that would violate immutability.

Many functions want the contract "I won't change this, but I don't care  
what anybody else does to it", so those are perfect candidates for const.   
The benefit is you can pass in mutable, const, or immutable data without  
an explicit cast.

Immutable functions can add extra optimizations to their code.  For  
example, you don't need to lock an immutable object to access its data.   
This kind of thing is very important for statically provable purity.

>
> -----------------
>
> Immutable structs/classes can be quite useful, they are safer, remove  
> some complexity from a program, they can be sometimes the right thing  
> you want (think about a Date object that keeps one day of the year),  
> help paralellism, and they may allow for other optimizations (for  
> example there's no need to copy them (so you can save memory and/or  
> allocations, just like for immutable strings), or on the opposite you  
> can have a copy of them on each CPU cache, and you are sure they will  
> not go out of sync, this allows for a program more scalable on  
> multi-cores).
>
> So I have tried to write a very simple program that uses immutable  
> structs and classes:
>
> immutable struct S {
>     int x;
>     this(int xx) { this.x = x; }
> }
>
> immutable class C {
>     int x;
>     this(int xx) { this.x = x; }
> }
>
> void main() {
>     auto s = S(10);
>     auto c = new C(10);
> }
>
>
> But the compiler outputs:
>
>
> Error: cannot implicitly convert expression (this) of type immutable(C)  
> to test.C
> test.d(8): Error: constructor test.C.this missing initializer for final  
> field x
> test.d(12): Error: constructor test.S.this (int xx) does not match  
> parameter types (int)
> test.d(12): Error: ((immutable immutable(S) __ctmp1 = 0;
>
> ) , __ctmp1).this can only be called on a mutable object, not  
> immutable(S)
>
>
> I don't understand such errors much. What is that I am doing wrong?
> Note that if you remove the "immutable" that program works, and if you  
> replace "immutable" with "invariant" the compiler gives thye same errors  
> (internally it keeps using immutable(C)).
>

Unfortunately, the whole thing is not completely fleshed out.  currently,  
the only way to make an immutable class instance is to make a mutable  
class instance, and cast it to immutable once you have constructed it.   
Therefore, saying all instances of a class are immutable renders it  
useless.

I don't really like the way this works, as the compiler is depending on  
the developer to ensure something marked as immutable really doesn't have  
any other mutable references to it.  This can be difficult if you don't  
know the contents of the class.

-Steve



More information about the Digitalmars-d mailing list