July 11, 2012
On 07/11/2012 04:16 PM, deadalnix wrote:
> On 11/07/2012 16:16, deadalnix wrote:
>> On 11/07/2012 16:04, Timon Gehr wrote:
>>> On 07/11/2012 02:58 PM, deadalnix wrote:
>>>> I don't think that is a big issue.
>>>>
>>>> Either the value isn't accessed often, and then it make no sense to
>>>> cache it, or it is accessed often and it make sense to precalculate the
>>>> cached value when building the object.
>>>>
>>>
>>> And sometimes it is not known in advance if it will be accessed at all.
>>> And this is somewhere in a class that seems unrelated to the object
>>> that wants to compute a string representation/hash value/comparison.
>>> It is not the simple cases that are an issue.
>>
>> Arguably, this is a software design problem. I never encountered a case
>> where I need to do such thing and never encountered something similar in
>> code except code that demonstrate trick or subverting language
>> features/librairies in unexpected ways (which is always fun to do, but
>> should never ends up in production or be promoted by a language/a lib).
>
> By the way, I'd be happy to be proven false, but I think the issue is
> overstated here.

Frankly, there is no real issue. It is always possible to sidestep the
built-in syntax-sugared library-supported functionality. The inefficiencies caused by the unused vtable slots are likely neglegible.
It's just not something one wants to do nor encourage to do.
July 11, 2012
On Wednesday, 11 July 2012 at 12:39:03 UTC, Andrei Alexandrescu wrote:

>
> I gave evidence on a large, high quality C++ codebase that the use of mutable (which is the solution of choice for memoization, caching, and lazy computation) is extremely scarce.
>
> What evidence do you have for your prediction?
>
>
> Andrei

Qt codebase (large, high quality) has around 1500 'mutable' keyword occurrences. The actual number of mutable declarations must be lower, but they are quite common. 'Extremely scarce' obviously does not apply there. Also, the ratio of occurrences of mutable vs const keywords is not a good metric for estimating logical const prevalence.

July 11, 2012
On Mon, 09 Jul 2012 07:44:24 -0400, Timon Gehr <timon.gehr@gmx.ch> wrote:

> On 07/09/2012 08:37 AM, Adam Wilson wrote:
>> Object is now const-correct throughout D. This has been a dream for many
>> of you. Today it is a reality.
>
> PITA. Forced const can severely harm a code base that wants to be
> flexible -- it leaks implementation details and is infectuous.
>
> Any options planned to allow not inheriting all the cruft from Object if it is of no use?
>
> Eg:
>
> // object.di
> class RawObject { }
> class Object : RawObject { ... }
>
> // user.d
> class C { }             // inherits from Object
> class D : RawObject { } // this does not
>

Two solutions:

1. object.opEquals(T : Object, U : Object) (T t, U u) which can use mutable opEquals for derived types
2. define a non-operator equality function, i.e. mutableEquals().  Can be attached to actual opEquals with struct wrapper.

These are not insolvable problems.

-Steve
July 11, 2012
On 11/07/2012 17:03, Jakob Ovrum wrote:
> On Wednesday, 11 July 2012 at 12:36:43 UTC, Andrei Alexandrescu wrote:
>> I was a long-time proponent of this. It's less exciting than it may
>> seem actually.
>>
>> (a) Classes that work with const just fine incur one extra virtual
>> call. I think this can be avoided by having the compiler plant the
>> same pointer for the const and non-const version in the vtable.
>>
>> (b) Classes that can't do as little as one of these four operations
>> without mutating the object are completely excluded from the
>> immutability system, even if they'd otherwise benefit from it. Even
>> those that don't "care" they need to actively _work_ on not caring,
>> which doesn't sit well.
>>
>> So I don't see this as a viable solution to people who are fine with
>> const, but would like to use e.g. some lazy computation.
>>
>>
>> Andrei
>
> This solution is not for allowing people to use lazy computation in
> their const overrides, it's for allowing people to still use opEquals,
> toString etc. even if their implementations cannot and should not be const.
>

In this case, they have function that does something else than compare test for equality, etc . . . The overload make no sense here in the first place, and the fact that const break such thing isn't a problem. This is the other way around, the fact that const break such a practice is good.
July 11, 2012
On 7/11/12 11:03 AM, Jakob Ovrum wrote:
> On Wednesday, 11 July 2012 at 12:36:43 UTC, Andrei Alexandrescu wrote:
>> I was a long-time proponent of this. It's less exciting than it may
>> seem actually.
>>
>> (a) Classes that work with const just fine incur one extra virtual
>> call. I think this can be avoided by having the compiler plant the
>> same pointer for the const and non-const version in the vtable.
>>
>> (b) Classes that can't do as little as one of these four operations
>> without mutating the object are completely excluded from the
>> immutability system, even if they'd otherwise benefit from it. Even
>> those that don't "care" they need to actively _work_ on not caring,
>> which doesn't sit well.
>>
>> So I don't see this as a viable solution to people who are fine with
>> const, but would like to use e.g. some lazy computation.
>>
>>
>> Andrei
>
> This solution is not for allowing people to use lazy computation in
> their const overrides, it's for allowing people to still use opEquals,
> toString etc. even if their implementations cannot and should not be const.
>
> e.g. the LuaD function I posted earlier - it has nothing to do with
> caching or lazy computation, it's just that it's only logically constant
> and cannot ever be bitwise constant due to the underlying API. Immutable
> instances of such structures are next to useless, as every member
> function except for a single getter function uses mutation.

I think I'll find it rather difficult to get behind modeling arbitrary escapes from immutability. If you want classes, you buy into a certain contract with inherent rights and constraints (starting with using references). It's a given, and again I find it unreasonable to ask that classes allow for arbitrary customization.

Your LuaD example goes like this:

    /**
     * Compare this object to another with Lua's equality semantics.
     * Also returns false if the two objects are in different Lua states.
     */
    bool opEquals(T : LuaObject)(ref T o) @trusted
    {
        if(o.state != this.state)
            return false;

        push();
        o.push();
        scope(success) lua_pop(state, 2);

        return lua_equal(state, -1, -2);
    }

You may be able to make this work by putting the state associated with push() and pop() in the Cache subsystem. If all else breaks, have opEquals assert(false, "Call bool lua_equals()").

We can't really model every possible design.


Andrei
July 11, 2012
On 7/11/12 11:11 AM, Max Samukha wrote:
> On Wednesday, 11 July 2012 at 12:39:03 UTC, Andrei Alexandrescu wrote:
>
>>
>> I gave evidence on a large, high quality C++ codebase that the use of
>> mutable (which is the solution of choice for memoization, caching, and
>> lazy computation) is extremely scarce.
>>
>> What evidence do you have for your prediction?
>>
>>
>> Andrei
>
> Qt codebase (large, high quality) has around 1500 'mutable' keyword
> occurrences.

How many lines total?

Andrei

July 11, 2012
On 07/11/2012 05:27 PM, deadalnix wrote:
> On 11/07/2012 17:03, Jakob Ovrum wrote:
>> On Wednesday, 11 July 2012 at 12:36:43 UTC, Andrei Alexandrescu wrote:
>>> I was a long-time proponent of this. It's less exciting than it may
>>> seem actually.
>>>
>>> (a) Classes that work with const just fine incur one extra virtual
>>> call. I think this can be avoided by having the compiler plant the
>>> same pointer for the const and non-const version in the vtable.
>>>
>>> (b) Classes that can't do as little as one of these four operations
>>> without mutating the object are completely excluded from the
>>> immutability system, even if they'd otherwise benefit from it. Even
>>> those that don't "care" they need to actively _work_ on not caring,
>>> which doesn't sit well.
>>>
>>> So I don't see this as a viable solution to people who are fine with
>>> const, but would like to use e.g. some lazy computation.
>>>
>>>
>>> Andrei
>>
>> This solution is not for allowing people to use lazy computation in
>> their const overrides, it's for allowing people to still use opEquals,
>> toString etc. even if their implementations cannot and should not be
>> const.
>>
>
> In this case, they have function that does something else than compare
> test for equality, etc . . . The overload make no sense here in the
> first place, and the fact that const break such thing isn't a problem.
> This is the other way around, the fact that const break such a practice
> is good.

I think this posts roots in a misunderstanding of 'cannot and should not be const'.
July 11, 2012
On Wednesday, 11 July 2012 at 15:28:41 UTC, Andrei Alexandrescu wrote:
> On 7/11/12 11:11 AM, Max Samukha wrote:
>> On Wednesday, 11 July 2012 at 12:39:03 UTC, Andrei Alexandrescu wrote:
>>
>>>
>>> I gave evidence on a large, high quality C++ codebase that the use of
>>> mutable (which is the solution of choice for memoization, caching, and
>>> lazy computation) is extremely scarce.
>>>
>>> What evidence do you have for your prediction?
>>>
>>>
>>> Andrei
>>
>> Qt codebase (large, high quality) has around 1500 'mutable' keyword
>> occurrences.
>
> How many lines total?
>
> Andrei

1512. Obtained by grepping the src directory of Qt 4.8.0, so the number includes duplicates, comments, etc. I think that even if the actual number is lower by an order, some 100 types using mutable still do not qualify for 'extremely scarce'. If I have time (which is unlikely), I will probably analyse the codebase for the actual number.

July 11, 2012
On 7/11/12 11:50 AM, Max Samukha wrote:
> On Wednesday, 11 July 2012 at 15:28:41 UTC, Andrei Alexandrescu wrote:
>> On 7/11/12 11:11 AM, Max Samukha wrote:
>>> On Wednesday, 11 July 2012 at 12:39:03 UTC, Andrei Alexandrescu wrote:
>>>
>>>>
>>>> I gave evidence on a large, high quality C++ codebase that the use of
>>>> mutable (which is the solution of choice for memoization, caching, and
>>>> lazy computation) is extremely scarce.
>>>>
>>>> What evidence do you have for your prediction?
>>>>
>>>>
>>>> Andrei
>>>
>>> Qt codebase (large, high quality) has around 1500 'mutable' keyword
>>> occurrences.
>>
>> How many lines total?
>>
>> Andrei
>
> 1512. Obtained by grepping the src directory of Qt 4.8.0, so the number
> includes duplicates, comments, etc. I think that even if the actual
> number is lower by an order, some 100 types using mutable still do not
> qualify for 'extremely scarce'. If I have time (which is unlikely), I
> will probably analyse the codebase for the actual number.

I was asking about total number of C++ code lines. In our codebase we have one use of "mutable" per 7659 lines of C++ code (as grep and wc count).

Andrei

July 11, 2012
On 11/07/2012 17:49, Timon Gehr wrote:
> On 07/11/2012 05:27 PM, deadalnix wrote:
>> On 11/07/2012 17:03, Jakob Ovrum wrote:
>>> On Wednesday, 11 July 2012 at 12:36:43 UTC, Andrei Alexandrescu wrote:
>>>> I was a long-time proponent of this. It's less exciting than it may
>>>> seem actually.
>>>>
>>>> (a) Classes that work with const just fine incur one extra virtual
>>>> call. I think this can be avoided by having the compiler plant the
>>>> same pointer for the const and non-const version in the vtable.
>>>>
>>>> (b) Classes that can't do as little as one of these four operations
>>>> without mutating the object are completely excluded from the
>>>> immutability system, even if they'd otherwise benefit from it. Even
>>>> those that don't "care" they need to actively _work_ on not caring,
>>>> which doesn't sit well.
>>>>
>>>> So I don't see this as a viable solution to people who are fine with
>>>> const, but would like to use e.g. some lazy computation.
>>>>
>>>>
>>>> Andrei
>>>
>>> This solution is not for allowing people to use lazy computation in
>>> their const overrides, it's for allowing people to still use opEquals,
>>> toString etc. even if their implementations cannot and should not be
>>> const.
>>>
>>
>> In this case, they have function that does something else than compare
>> test for equality, etc . . . The overload make no sense here in the
>> first place, and the fact that const break such thing isn't a problem.
>> This is the other way around, the fact that const break such a practice
>> is good.
>
> I think this posts roots in a misunderstanding of 'cannot and should not
> be const'.

If it cannot and should not be const, it isn't a comparison or an equality test, it is another operation altogether that is performed.