Logical const

Steven Schveighoffer schveiguy at yahoo.com
Mon Nov 29 08:24:56 PST 2010


On Mon, 29 Nov 2010 10:56:14 -0500, Andrei Alexandrescu  
<SeeWebsiteForEmail at erdani.org> wrote:

> On 11/29/10 8:56 AM, Steven Schveighoffer wrote:
>> On Sat, 20 Nov 2010 09:21:04 -0500, Peter Alexander
>> <peter.alexander.au at 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.
>
> In fact it's possible to provide logical const with guarantees. You need  
> a construct that keeps together a bool, a pure function/delegate/method,  
> and a value, and works like this:
>
> class X
> {
>      int x;
>      lconst int y = { return x + 42; };
>      void m1() { x = 2; invalidate(y); }
>      void m2() const { writeln(y); }
> }
>
> You can use the intrinsic invalidate() against a non-const lconst field,  
> but not against const lconst. Reading that field checks whether the  
> field has been invalidated. If so, it writes the field with the result  
> of the function/delegate/method and turns the validation flag on.
>
> With this system in place, I think the lconst value is guaranteed to be  
> as strong as const.

This only solves the caching issue (which I agree is a large issue).   
There are other cases where you want a mutable pointer to other data that  
the object does not own.  Such as a widget having a pointer to its  
window.  Assuming that window draw routines need to be non-const, a widget  
cannot draw itself.  You need to keep the widget to window relationship  
outside the class, or cast.  Both of these solutions are awkward at best.

> I recall I managed to convince Walter that the system works, but we  
> agreed it would cost too much for what it does. I think it can be  
> implemented as a library artifact under certain assumptions.

It would be nice to have user-defined annotations, so we could play with  
possible implementations.  As I recall, the acceptance of annotations in D  
had not occurred when logical const was last discussed, and this seems  
like a perfect candidate for annotations.

-Steve


More information about the Digitalmars-d mailing list