February 19, 2013
On Tuesday, 19 February 2013 at 08:25:08 UTC, kenji hara wrote:
> I have said that "method const qualifier inference on class inheritance is
> bad".
>
> With 8138 or 8366, such inference suddenly add const qualifier to one of
> overloaded functions, and changes the meaning of overload list. More than
> worse, it may introduce newly relation between overloaded functions, and in
> the worst case, it will add new forward reference problem.
>
> class C : B  // or class C(T)
> {
>     void foo() { ... foo(10);  ... }
>     void foo(int n) { ... foo(); ... }
> }
>
> For pure/nothrow/@safe inference, if a mutual dependency is found, the
> attributes are inferred to impure/throwing/@system due to avoid forward
> reference issue.
> But, we cannot define such 'default qualifier' for const inference. So it
> must raise  forward reference error if a mutual dependency is found. AND it
> will break existing valid code.
>
> And bug 8366 can allow to hijack derived class by base class. If a base
> class add const qualifier to its method, it affects to the overload list in
> its derived class, not only the method that directly overrides modified one.
>
> We should avoid language features that is hijacking/fwdref error prone.
>
> Kenji Hara

I have no reason not to trust your great experience on this matter. Is syntax sugar a possible solution?

class A
{
    bool foo(in Object o) inout { return true; }
}

... lowers to:

class A
{
    bool foo(in Object o) { return true; }
    bool foo(in Object o) const { return true; }
}

Or would that lead to extensive problems of its own?
February 20, 2013
On Tuesday, 19 February 2013 at 16:57:33 UTC, Zach the Mystic wrote:
> On Tuesday, 19 February 2013 at 08:25:08 UTC, kenji hara wrote:
>> I have said that "method const qualifier inference on class inheritance is
>> bad".
>>
>> With 8138 or 8366, such inference suddenly add const qualifier to one of
>> overloaded functions, and changes the meaning of overload list. More than
>> worse, it may introduce newly relation between overloaded functions, and in
>> the worst case, it will add new forward reference problem.
>>
>> class C : B  // or class C(T)
>> {
>>    void foo() { ... foo(10);  ... }
>>    void foo(int n) { ... foo(); ... }
>> }
>>
>> For pure/nothrow/@safe inference, if a mutual dependency is found, the
>> attributes are inferred to impure/throwing/@system due to avoid forward
>> reference issue.
>> But, we cannot define such 'default qualifier' for const inference. So it
>> must raise  forward reference error if a mutual dependency is found. AND it
>> will break existing valid code.
>>
>> And bug 8366 can allow to hijack derived class by base class. If a base
>> class add const qualifier to its method, it affects to the overload list in
>> its derived class, not only the method that directly overrides modified one.
>>
>> We should avoid language features that is hijacking/fwdref error prone.
>>
>> Kenji Hara
>
> I have no reason not to trust your great experience on this matter. Is syntax sugar a possible solution?
>
> class A
> {
>     bool foo(in Object o) inout { return true; }
> }
>
> ... lowers to:
>
> class A
> {
>     bool foo(in Object o) { return true; }
>     bool foo(in Object o) const { return true; }
> }
>
> Or would that lead to extensive problems of its own?

The problem is now that you may overload on or the other function in derived classes. Such a surprising behavior is not acceptable IMO.

As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?
February 20, 2013
On Wednesday, 20 February 2013 at 06:00:02 UTC, deadalnix wrote:
> On Tuesday, 19 February 2013 at 16:57:33 UTC, Zach the Mystic
>> I have no reason not to trust your great experience on this matter. Is syntax sugar a possible solution?
>>
>> class A
>> {
>>    bool foo(in Object o) inout { return true; }
>> }
>>
>> ... lowers to:
>>
>> class A
>> {
>>    bool foo(in Object o) { return true; }
>>    bool foo(in Object o) const { return true; }
>> }
>>
>> Or would that lead to extensive problems of its own?
>
> The problem is now that you may overload one or the other function in derived classes. Such a surprising behavior is not acceptable IMO.

It's not that surprising, IMO. If only one is defined in the base class, 'override' would give an error:

class A
{
  bool foo(in Object o) { return true; }
}

class B : A
{
  // This:
  override bool foo(in Object o) inout { return false; }
  // ...would translate to this:
  override bool foo(in Object o) { return false; } // Pass
  override bool foo(in Object o) const { return false; } // Error
}

The 'const', when overridden, would naturally give an error, since it's not overriding anything. If there are already two defined in the base, then the new overridden 'inout' is exactly what you want, two new functions for the derived. If there's nothing in the base, then 'override' won't work for either of the functions it declares.

> As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?

I'm taking it as given that Kenji Hara knows what he's talking about when he says that a single function is no good. I don't understand it fully, but I'm trying to work within the context of what he says. I think he doesn't want to disturb the way the vtable is built, and inferring const seems to force the addition of another function into the table, but only when it is used, and so you can't tell what the vtable is supposed to look like until you've processed all calls to the const-inferring function. And to make the two do exactly the same thing is asking for trouble if you end up overloading one - then you could break const-ness by only overloading the mutable one in a derived class. The forward referencing problem is beyond my comprehension at the moment, but Hara is convinced its a fatal flaw in the system.
February 20, 2013
On Wednesday, 20 February 2013 at 07:42:56 UTC, Zach the Mystic wrote:
> On Wednesday, 20 February 2013 at 06:00:02 UTC, deadalnix wrote:
>> On Tuesday, 19 February 2013 at 16:57:33 UTC, Zach the Mystic
>>> I have no reason not to trust your great experience on this matter. Is syntax sugar a possible solution?
>>>
>>> class A
>>> {
>>>   bool foo(in Object o) inout { return true; }
>>> }
>>>
>>> ... lowers to:
>>>
>>> class A
>>> {
>>>   bool foo(in Object o) { return true; }
>>>   bool foo(in Object o) const { return true; }
>>> }
>>>
>>> Or would that lead to extensive problems of its own?
>>
>> The problem is now that you may overload one or the other function in derived classes. Such a surprising behavior is not acceptable IMO.
>
> It's not that surprising, IMO. If only one is defined in the base class, 'override' would give an error:
>
> class A
> {
>   bool foo(in Object o) { return true; }
> }
>
> class B : A
> {
>   // This:
>   override bool foo(in Object o) inout { return false; }
>   // ...would translate to this:
>   override bool foo(in Object o) { return false; } // Pass
>   override bool foo(in Object o) const { return false; } // Error
> }
>
> The 'const', when overridden, would naturally give an error, since it's not overriding anything. If there are already two defined in the base, then the new overridden 'inout' is exactly what you want, two new functions for the derived. If there's nothing in the base, then 'override' won't work for either of the functions it declares.
>
>> As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?
>
> I'm taking it as given that Kenji Hara knows what he's talking about when he says that a single function is no good. I don't understand it fully, but I'm trying to work within the context of what he says. I think he doesn't want to disturb the way the vtable is built, and inferring const seems to force the addition of another function into the table, but only when it is used, and so you can't tell what the vtable is supposed to look like until you've processed all calls to the const-inferring function. And to make the two do exactly the same thing is asking for trouble if you end up overloading one - then you could break const-ness by only overloading the mutable one in a derived class. The forward referencing problem is beyond my comprehension at the moment, but Hara is convinced its a fatal flaw in the system.

What would be nice is if the vtable could get its two functions, but have them both point to the same one in the end, to save space in the binary file. But I think the forward reference problem might interfere with that too (although, as I said, I don't fully understand it).
February 20, 2013
On Wednesday, 20 February 2013 at 06:00:02 UTC, deadalnix wrote:
> As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?

I use overloading of const/immutable in one of my projects to avoid a string copy when possible:

https://github.com/JakobOvrum/Dirk/blob/master/irc/client.d#L332

Granted, here const does not apply to the implicit `this` parameter, but it is essentially the same thing.
February 20, 2013
On Wednesday, 20 February 2013 at 08:25:45 UTC, Jakob Ovrum wrote:
> On Wednesday, 20 February 2013 at 06:00:02 UTC, deadalnix wrote:
>> As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?
>
> I use overloading of const/immutable in one of my projects to avoid a string copy when possible:
>
> https://github.com/JakobOvrum/Dirk/blob/master/irc/client.d#L332
>
> Granted, here const does not apply to the implicit `this` parameter, but it is essentially the same thing.

Yes I know that usage. That is different for this, because of overload problems. For parameter that isn't really an issue.

As of you case specifically, I wouldn't do that, because you have no gain in duplicating the string in the function rather than before passing it. I however don't deny that this may be useful in some cases. It cause quite a lot of trouble with overloads.
February 20, 2013
On Wed, 20 Feb 2013 01:00:00 -0500, deadalnix <deadalnix@gmail.com> wrote:

> As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?

const(T) and T are different types.  Saying you can overload on types, unless they just vary by const is a special case that I don't think is worth adding.

-STeve
February 21, 2013
On Wednesday, 20 February 2013 at 13:42:48 UTC, Steven Schveighoffer wrote:
> On Wed, 20 Feb 2013 01:00:00 -0500, deadalnix <deadalnix@gmail.com> wrote:
>
>> As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?
>
> const(T) and T are different types.  Saying you can overload on types, unless they just vary by const is a special case that I don't think is worth adding.
>

Explain me how the hell you overload on implicit parameter types ?
February 21, 2013
On Wed, 20 Feb 2013 21:50:01 -0500, deadalnix <deadalnix@gmail.com> wrote:

> On Wednesday, 20 February 2013 at 13:42:48 UTC, Steven Schveighoffer wrote:
>> On Wed, 20 Feb 2013 01:00:00 -0500, deadalnix <deadalnix@gmail.com> wrote:
>>
>>> As discussed previously, I really wonder hy a const and non const version of a function can exists in a first place. What problem does it solve that isn't better solved by inout ?
>>
>> const(T) and T are different types.  Saying you can overload on types, unless they just vary by const is a special case that I don't think is worth adding.
>>
>
> Explain me how the hell you overload on implicit parameter types ?

A method is simply a function that takes a hidden parameter of an object or struct.

Really, a method with a signature Obj.foo() is a function with a signature foo(Obj this)

A const method Obj.foo() const is a function with a signature foo(const(Obj) this)

So it's equivalent to saying you can overload:

foo(int *x)
foo(const(int) *x)

To disallow this would be unnecessarily restrictive.

-STeve
February 21, 2013
On Wednesday, 20 February 2013 at 09:44:39 UTC, deadalnix wrote:
> As of you case specifically, I wouldn't do that, because you have no gain in duplicating the string in the function rather than before passing it.

You should look more closely. It's not unconditionally duplicated.