I want to implement the value object pattern in D. That is, I want to have mutable reference variables to immutable objects. T variables should be assignable, but T objects should never change their state.
I am confused about the difference between const and immutable in D. Let me illustrate my doubts with a skeleton Rational class:
class Rational
{
int num;
int den;
Should I declare num and den as const or immutable? Is there a difference for integers?
invariant()
{
assert(den > 0);
assert(gcd(abs(num), den) == 1);
}
Should I declare invariant as const or immutable? Marking it as immutable results in a compile-time error, but that may be due to other members not being marked immutable.
this(int numerator, int denominator) { ... }
Should I declare the constructor as const or immutable? What would that mean?
string toString()
{
return std.string.format("(%s / %s)", num, den);
}
}
Should I declare toString as const or immutable?
Instead of marking individual members, it seems I can also mark the entire class:
class Rational
const class Rational
immutable class Rational
Which of these make the most sense for the value object pattern?
What about pure? In the value object pattern, the methods should be free of side effects, so does it make sense to declare every member as pure? Marking toString as pure does not compile, unfortunately, because std.string.format is not pure; is there any particular reason for that?
It seems I can also declare the class itself as pure, but that does not seem to have any effect, because the compiler does not complain about toString calling an impure function anymore.
What does it mean to declare a class as pure then? Is it simply ignored?