On 11/29/2010 11:56 PM, Steven Schveighoffer wrote:
On Sat, 20 Nov 2010 09:21:04 -0500, Peter Alexander
<peter.alexander...@gmail.com> wrote:

D does not support logical const due to the weak guarantees that it
provides.

So, without logical const, how are D users supposed to provide lazy
evaluation and memoization in their interfaces, given that the
interface should *seem* const, e.g.

class Matrix
{
double getDeterminant() const { /* expensive calculation */ }
}

If it turns out that getDeterminant is called often with the raw
matrix data remaining unchanged, how can we add caching to this class
without rewriting the const-ness of all code that touches it?

This has been discussed at length on this newsgroup, and I argued for it
for a long time. You will not get any traction with Walter, because I've
already proven that logical const == const, and it still doesn't change
his mind.

The thing is we *already* have a hidden field that is logically const --
an object's monitor. Regardless of an object's constancy, you can always
mutate the monitor. The compiler does it by logically inserting a cast
away from const, so that's what I'd suggest.

In reality, once you get into the realm of logical const, the compiler
no longer helps you. Any guarantees are now provided by you, not the
compiler.

I've proposed a very complex system to allow you to indicate only
certain fields as const which also worked with the existing const
system. While I think Walter and Andrei agreed it was possible, I agreed
with them that it was too complex to ask users to deal with.

What I'd like to see is a solution like this:

struct S
{
@mutable int i;
int x;
}

S s;

lconst(S) *ls = &s; // new keyword!

ls.x = 5; // error
ls.i = 5; // OK

const(S) *cs = &s;
ls = cs; // error, less restrictive const version

I think a library solution would be more crude than what the compiler
could do in this regard. But another keyword, and complicating the const
system further is probably too much tax for this feature.

In the end, I'd say just cast away const for the fields you want to
change, and at least you can get your work done.

And how do we write generic code when it's practically impossible to
determine const-ness from a glance? e.g. getDeterminant looks like it
should be const, but wouldn't be if it had caching, so writing generic
code that uses getDeterminant would be very difficult.

This is the point of Walter's objection. Logical const is not const, so
you would not be able to guarantee anything when you see const.

This kind of feature should only be used where the 'mutable' member is
not considered part of the state of the object. I.e. a cached
calculation is a good example of this. This rule is not enforceable, so
it is up to you to determine applicability.

-Steve

This entire thread has been very instructive. Thanks everybody.

This post is the one that, in my humble opinion of C++ game developer (like the original poster), moves more towards a solution.

I have one question though, that comes from the "C++ const being totally ignored by dmc's optimizer", combined with the emphasys on D's const being verifiable by dmd:

Is the "const" keyword (both in C++, and in D) for the developer writing code, or for the compiler compiling it?

From what Walter said (and it makes a lot of sense to me), in the case of C++ it is only a hint to the programmer that the compiler will enforce you, but internally the compiler cannot really use it for anything.

On the other side, in D, it is a hint to the compiler but it will only use it if is verifiable. If that is the case, why do we need the "const" keyword in the first place? The compiler can already verify that the code is const and do the proper opimizations.

Steve's solution would be on the side of "useful for the programmer, enforced by the compiler, uselss for the compiler".

Please let me know if i wrote something that doesn't make sense.

Jordi

Reply via email to