On Sun, Apr 03, 2022 at 03:42:15PM -0700, Ali Çehreli via Digitalmars-d-learn wrote: [...] > In any case, there is no logical constness in D. (However, one can > play tricks like using casts. (Which may be undefined behavior, etc. > etc.)) [...]
A thought occurred to me. What is logical const, and how can we make it useful? Useful meaning, it's not just a convention (like in C++) with no hard guarantees and no verifiability. Currently, D has physical const, so `const` cannot be used for things like caching, lazily-initialized objects, and other things that are logically const but not physically const because mutation is involved. But what really is physical const? It's essentially a contract, guaranteed by the language and statically verified by the compiler, that the physical data has not changed. IOW, it's a contract stating that the data physically stored before operation X is identical to the data physically stored after operation X, and that it has not changed in the meantime. Now can we extend this concept to logical const? Perhaps in this way: instead of guaranteeing the physical data is unchanged, what about a contract that guarantees that *externally-observable behaviour* of the object is unchanged? Meaning, the object may actually have changed internally, but as long as this cannot be observed externally (and this includes *future* behaviour of the object -- so we're not just slipping internal state changes under the carpet that may later alter the object's behaviour), to the outside world it behaves as though it were actually const. In the case of lazy initialization, for example, it ought to be provable that the value of the object, as observed by the outside world, cannot change. The initial state where the value is uninitialized is not observed by the outside world; the only observable value only appears after initialization, and does not change henceforth. Similarly for a cached value: it ought to be provable that the first computation of value is the *only* value that can be externally observed; after the initial computation, the value will never change again. In some sense, this is like an extension of ctors initializing immutable values. The compiler tracks whether the variable has been initialized yet, and inside the ctor you can assign to immutable because the uninitialized value is not observable from outside before that. Once assigned, the compiler enforces no subsequent changes. It's also like D's extension of purity, where impure operations are allowed as long as the outside world cannot tell the difference. There should be some way of implementing logical const along these lines that still provides guarantees whilst relaxing the physical immutability rule. T -- It only takes one twig to burn down a forest.