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