Logical const

Jonathan M Davis jmdavisProg at gmx.com
Sun Nov 28 07:45:42 PST 2010


On Sunday 28 November 2010 06:50:53 Peter Alexander wrote:
> On 28/11/10 11:25 AM, Jonathan M Davis wrote:
> > So, _I_ am certainly not aware of a good solution, but if you play games,
> > you should be able to get _something_ working. Overall though, I think
> > that the lesson is that you should really be making const functions
> > truly const and not try and deal with logical const at all.
> 
> Thanks for the reply Jonathan.
> 
> Your wording here worries me a little. You seem to be implying that
> logical const is some sort of arbitrary style choice, rather than a need
> that arises from real-life scenarios.
> 
> The only way you can write D-style const correct code is if you possess
> a crystal ball that will tell you whether you plan to cache accessors in
> the future. No real person can do that, so for all practical purposes,
> writing const correct code in D is impossible.
> 
> Again, the Matrix example: the *only* way to implement caching is to
> make getDeterminant() a non-const method. Great. That would be fine if
> the change was nice and localised, but what about other functions that
> use Matrix?
> 
> e.g.
> Matrix getInverse(const Matrix m) { ... }
> 
> Getting the inverse of a matrix requires that you calculate its
> determinant, so this function won't work anymore because I can't call
> getDeterminant() with a const Matrix. The only choice I have now is to
> make getInverse take a non-const Matrix:
> 
> Matrix getInverse(Matrix m) { ... }
> 
> Solves the problem, but now I've created a new one: getInverse now has
> complete write access to my matrix, so when I do something as harmless as:
> 
> Matrix inv = getInverse(myMatrix);
> 
> This innocent call has now lost the guarantee that myMatrix will come
> out unmodified.
> 
> But wait, there's more:
> 
> class GameObject
> {
>     ...
>     const Matrix getWorldTransform() const { return m_worldTransform; }
>     Matrix m_worldTransform;
> }
> 
> void renderGameObject(const GameObject obj) { ... }
> 
> What happens if renderGameObject needs to use getInverse, or
> getDeterminant?
> 
> 1. I have to change getWorldTransform to be a non-const function that
> returns a non-const Matrix.
> 
> 2. renderGameObject needs to be changed to receive a non-const GameObject.
> 
> 3. I have lost any guarantee that rendering my GameObjects won't destroy
> them...
> 
> Surely I'm not the only person that finds something *incredibly* wrong
> with this!?

Oh, I agree that the lack of logical const is a problem, but allowing for 
mutable member variables within a const object is a whole in the const system, 
and Walter, at least, is convinced that doing so is completely broken. 
Certainly, because of immutable in D, I have to agree that in the general case, 
it wouldn't work. Without immutable, you could presumably get something similar 
to what C++ has (if you could ever get Walter to go for it), but once you have 
immutable, that doesn't work anymore, since anything that's const could actually 
be immutable, and then it's _definitely_ impossible to change it.

From what I can tell of the current situation, either you make something const 
and guarantee that it's actually constant (which would tend to mean that you're 
_not_ going to get things like caching - which honestly, is something that most 
objects don't need anyway - though obviously there are those where it can help a 
great deal), or you maintain the state that you want outside the object and 
manipulate that. I believe that someone else suggested have an associative array 
as a cache outside of the object. That way, you could grab the value from there 
instead. And if you had to calculate a new value, you'd be free to stick it in 
the external associate array (or whatever you wanted to use to hold the cache).

Regardless, with how D works, in the general case, if you want something to be 
const, you're going to have to actually let it be const. That means no logical 
const unless you play games with stuff outside of the object (which 
unfortunately, throws purity out the window). It's certainly a problem, but it's 
not a problem with most objects, and it's not like we're going to talk Walter 
into using mutable like in D. And with immutable in the language, you couldn't 
do it anyway.

So, yes it's a problem. But as far as I can tell, it's one that we're stuck 
with.

- Jonathan M Davis


More information about the Digitalmars-d mailing list