On Tue, 28 Apr 2009 13:43:48 -0400, bearophile <[email protected]> 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

Reply via email to