On Tue, Aug 28, 2018 at 08:18:57AM +0000, Eugene Wissner via Digitalmars-d 
wrote:
[...]
> There are still valid use cases where const should be "broken". One of
> them is mutex (another one caching). I have very little experiance in
> multi-threaded programming, but what do you think about "mutable"
> members, despite the object is const?

The problem with compromising const is that it would invalidate any
guarantees const may have provided.  Const in D is not the same as const
in languages like C++; const in D means *physical* const, as in, the
data might reside in ROM where it's physically impossible to modify.
Allowing the user to bypass this means UB if the data exists in ROM.

Plus, the whole point of const in D is that it is machine-verifiable,
i.e., the compiler checks that the code does not break const in any way
and therefore you are guaranteed (barring compiler bugs) that the data
does not change.  If const were not machine-verifiable, it would be
nothing more than programming by convention, since it would guarantee
nothing.  Allowing const to be "broken" somewhere would mean it's no
longer machine-verifiable (you need a human to verify whether the
semantics are still correct).

Many of D's const woes can actually be solved if we had a
language-supported way of declaring the equivalence between const(U!T)
and U!(const(T)), AKA head-mutable.  The language already supports a
(very) limited set of such conversions, e.g., const(T*) is assignable to
const(T)*, because you're just making a copy of the pointer, but the
target is still unchangeable.  However, because there is no way to
specify such a conversion in a user-defined type, that means things like
RefCounted, or caches, or mutexes, cannot be made to work without either
ugly workarounds or treading into UB territory by casting away const.

But if there is a way for a user-defined template U to define a
conversion from const(U!T) to U!(const(T)) (the conversion code, of
course, would have to be const-correct and verifiable by the compiler),
then we could make it so that U!(const(T)) contained a mutable portion
(e.g., the refcount, mutex, cache, etc.) and an immutable portion (the
reference to the const object).


T

-- 
In order to understand recursion you must first understand recursion.

Reply via email to