Why D needs tail const
Stewart Gordon
smjg_1998 at yahoo.com
Wed Mar 28 06:54:47 PDT 2012
With arrays and pointers, you can declare
const(int[]) constData;
immutable(int[]) immutableData;
to enforce constancy constraints. The type modifiers apply both to the reference to the
data and to the data being referenced. If you want to be able to change what data the
variables reference, just not change the data itself, no problem:
const(int)[] constData;
immutable(int)[] immutableData;
However, this can't be done with classes. You can't do it with language builtins, anyway.
Rather, a class object reference is either mutable, const or immutable, and this
simultaneously affects both the reference itself and the referenced object.
This is unideal. Whether a reference to an object can change what it refers to and
whether the object itself can change are two distinct concepts.
OK, so we have std.typecons.Rebindable. But I've found it a PITA when it comes to generic
programming. Among other things, if you try to pass it around, you can end up with a mess
like const(Rebindable!(const(....))). This wouldn't happen with built-in tail const support.
I guess that, at the code level, tailConst and tailImmutable would be just type modifiers.
But at the semantic level, they're just the const and immutable modifiers we already
have being applied at a different level. So:
- tailConst(int[]) would be equivalent to const(int)[]
- tailConst(Class) would be a whole new type modification, under which the reference can
be reassigned, but the object's state cannot be changed through this reference, and when
calling methods of it the this pointer is const.
- const(tailConst(anything)) would just be the same as const(anything)
- tailConst(Struct) would just collapse to Struct if the struct contains no references or
only const and/or immutable references. Otherwise, it would be a distinct type modifier
that forces all references within the struct to be const. (Should we allow struct methods
to be qualified as tailConst/tailImmutable?)
- tailImmutable would work in the same way.
- You could have more involved constructs like const(tailImmutable(Class))[]. This would
be an array of constant references to immutable objects. So through this array reference,
neither what objects are in the array nor the objects themselves can be changed. But
there may also exist a tailImmutable(Class)[] referencing the same block of memory,
through which what objects are in the array can be changed, but the objects themselves
remain immutable.
So essentially, where the columns denote top-level constancy and the rows the next level down:
| mutable const immutable
----------+-------------------------------------------------
mutable | <no mod>
const | tailConst const
immutable | tailImmutable const(tailImmutable) immutable
Moreover, who thinks it would be nice if immutable classes could behave just like
primitives? Java gets partway there with String and others - you can just declare a
String variable and assign to it as you would an integer, and be confident that some
outside process won't change the contents of the variable behind your back. D could be
there with such improvements as built-in tail immutable (and making it the default
modifier when a variable of an immutable class is declared).
What do people think to the whole idea?
Stewart.
More information about the Digitalmars-d-announce
mailing list