July 27, 2004
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opsbrrs9pv5a2sq9@digitalmars.com...
> Aren't you only 'overloading/overriding' if the function signature is identical?

No. The rule is the names are looked up first, *then* overload resolution happens. In your example below, abc is found in the current scope. oload1.abc is not found in the current scope, and therefore does not participate in function overload resolution.

> Otherwise you're providing a specialisation i.e.
>
> [oload1.d]
> module oload1;
> void abc(int abc) {}
>
> [oload2.d]
> module oload2;
> import oload1;
>
> void abc(long abc) {}
>
> void main()
> {
> foo(1);
> foo(1L);
> }
>
> The above prints "long" twice, which isn't desired.
>
> The 'abc' provided by oload2 does _not_ override 'abc' provided by oload1 it's a different function signature.
>
> I agree that if it did override, it should be an error, one you could catch at compile time, one that you could solve by using an alias to specify the one you mean.
>
> Regan.
>
> -- 
> Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/


July 27, 2004
In article <ce48ge$1klr$1@digitaldaemon.com>, parabolis says...
>
>You argue that in the current D language, call it Dc, your error is caught. In the proposed language, call it Dp, you error is not caught and a bug is born. So you would like to believe that the total number of bugs in Dp is 1 more than Dc.

Yes I would :)

>However you failed to account for the bugs in the Dc library that are not in the Dp library. I believe there would be more bugs for two reasons:
>
>   1) If you can make a mistake like the one above, then consider
>the library writers who were forced to sprinkle extra function stubs throughout their code.

Well, all that's needed is an alias, not a full stub, but that's pretty much the same thing.  I like the stubs because they're explicit.  Requiring their presence gives the programmer more control over how call resolution is handled.

>   2) Since Dc has an exception to a rule that Dp does not you must ask
>yourself how many library writers only partly understand the exception and end up writing buggy code.

Every language has a feature set that a would-be programmer has to learn.  I think either way there will be the same number of ignorant programmers making approximately the same number of stupid mistakes.  Frankly, I'm on the fence regarding this issue.  In the presence of multiple inheritance I would be firmly in the C++ camp, but without it I could probably be convinced that the proposed solution is better.  What I've been hoping for is that someone will come up with a good concrete example of why one or the other is problematic.  I'm not concerned with convenience so much as with the prevention of subtle errors and with maintaining a predictable and intuitive set of rules.  I think the C++ scheme provides that and I think the proposed scheme *may* provide that, but I worry that I just haven't come up with a good enough reason why it does not.


Sean


July 27, 2004
"Derek Parnell" <derek@psych.ward> wrote in message news:ce4bb2$1liq$1@digitaldaemon.com...
> >> WHAT!?!? The coder has *explicitly* said he wanted an 'int'/'long'/'uint'... argument but D just went and converted to
'double'
> >> anyhow.
> > That's normal behavior, it's the integral argument promotion rules in C
and
> > C++ which survives intact in D.
> ...and 'normal' is equivalent to 'desirable', right? It seems wrong to me that if I _explicitly_ code an integer that the compiler silently converts this to something else *before* checking for a matching method signature.

No, that's not what's happening. What is happening is that name lookup happens *before* signature matching. When a name is found, *only* matching names in that name's scope are checked for a signature match. In this case, the only name in the scope takes a double argument, and an int is implicitly convertible to a double, hence it is a match.


> > But it's implicitly convertible to a double.
> It's also implicitly convertible to many other things too! So why pick on 'double'?

Because the only name in the scope takes a double as an argument.


> > as the aliases become part of the names in a scope, and so get carried
along
> > with the other names with a subsequent alias. And I'd add that if one actually wrote such an inheritance graph like that, the aliases are a
good
> > thing because they show you *intended* to overload them based on names
from
> > another scope.
>
> Okay, so I need to read
>
>    alias /classX/./funcA/ /funcB/
>
> in this context as
>
> "Assume that all the methods called /funcA/ from /classX/ (and whatever it has aliased) have been typed into this class, but are called /funcB/ in this class."

Yes.

> It just that I would have thought that just by deriving a class from another, the coder is already explicitly saying that they intend to use
the
> methods in the super-class. To me this seems a normal (there's that word again) thing to do. Otherwise it like saying "Derive classX from classY
and
> use methods A, B, and D from classY, and not any others.". Whereas I tend to think along the lines of "Derive classX from classY except for methods C, E and F".
>
> I will readjust my thinking, of course, as I don't expect D will change in this respect ;-)

The only rule to remember here is that name lookup happens before overload resolution <g>.


July 27, 2004
"Sean Kelly" <sean@f4.ca> wrote in message news:ce4gr1$1njs$1@digitaldaemon.com...
> In article <ce48ge$1klr$1@digitaldaemon.com>, parabolis says...
> >
> Well, all that's needed is an alias, not a full stub, but that's pretty
much the
> same thing.  I like the stubs because they're explicit.  Requiring their presence gives the programmer more control over how call resolution is
handled.

Minor detail: You'll forgive me for not wishing to confuse the Interface Resolution issue with that of the peek-a-boo game ~ one cannot alias a super-class method to fulfill an interface contract. You are simple forced to stub & dispatch. At any level of complexity, these stubs become a real issue.

> Every language has a feature set that a would-be programmer has to learn.
I
> think either way there will be the same number of ignorant programmers
making
> approximately the same number of stupid mistakes.  Frankly, I'm on the
fence
> regarding this issue.  In the presence of multiple inheritance I would be
firmly
> in the C++ camp, but without it I could probably be convinced that the
proposed
> solution is better.  What I've been hoping for is that someone will come
up with
> a good concrete example of why one or the other is problematic.  I'm not concerned with convenience so much as with the prevention of subtle errors
and
> with maintaining a predictable and intuitive set of rules.  I think the
C++
> scheme provides that and I think the proposed scheme *may* provide that,
but I
> worry that I just haven't come up with a good enough reason why it does
not.

Did you see what Regan proposed? <g>


July 27, 2004
I see some things that I'd like to clarify and expand upon, if I may:

1)

These three related issues have somehow turned into a vague Java vs C++ debate. That is not what I had in mind at all. Rather, these issues identify "special case" situations where things don't happen as one might expect. That, of course, is based upon the assumption that you'd expect a sub-class to inherit all its super-class methods (non private). What I'm advocating is symmetry and consistency ~ inversely: a lack of special cases. Certainly, any system of appropriate complexity will tend to exhibit some kind of special-case scenario, but surely we can agree that those should be minimized? The document was intended to highlight the area of name resolution as apparently riddled with special cases, and that something should be done about it.

2)

What I personally find truly frustrating about the current situation is this: Walter effectively states "it works for me" and that's that. Doesn't matter that there could be a far superior mechanism in existence, or that someone from the NG might be primed with a truly spectacular solution. Such an approach is often termed "stonewalling".

Yes, some additional tact might not go amiss on my part; yet past experience on this NG indicates such an approach has little benefit with respect to addressing issues. One example that immediately leaps to mind is the Interface debacle at the beginning of April. For those who don't recall, Walter railed black-against-white that D had all the Interface support one could ever need, and deflected every argument and position in a manner similar to recent responses. The "Interface Expose" was subsequently posted to illustrate just how much bullshit was involved (and I was simply the last in a long procession of those who battled to get the point across). There was an explicit note made at the time about the lack of Contract Resolution Through Inheritence (dated April 9th; 2004. It was termed "manifest" within that document. Email sent to Walter on April 7th). That particular issue is simply raising its head once more.

This is why the current document "appeared" without prior debate (Walter did acknowledge a pre-post courtesy copy).

3)

I do not profess to be an expert at anything. Rather, I'm pointing out where some things in D just don't seem right. Having written a reasonably substantial body of code in D (35,000 lines), I think I have a feel for that. The /real/ issue at hand is that of confusion: Three confusing situations in one single area of the language is surely a problem, and I really do think something needs to be done about it. Of course, I might be completely and thoroughly misguided instead.

Thank you;  now, I really must get on with my life.

- Kris


July 27, 2004
In article <ce48ge$1klr$1@digitaldaemon.com>, parabolis says...
>
>I see your point and that would be a nasty bug to track down. In this instance the inheritance bug actually seems to be a feature. But I believe that your argument misses a subtle point.

Okay, I've modified my example a bit, but doing so has me reconsidering a bit. Here it is:

interface I { void foo(); }
interface J { void foo(); }

class A : I { void foo() { printf( "I\n" ); } }
class B : A {}
class C : B {}
class D : C {}
class E : D {}
class F : E, J { void foo() { printf( "J\n" ); } }

int main()
{
F f = new F();
I i = f;
J j = f;
i.foo();
j.foo();
return 0;
}

As you might expect, this prints:

J
J

Because member functions are virtual by default in D, I'm now inclined to support the inheritance proposal.  It just seems more consistent all around. But if anyone can offer a good reason why the proposed scheme doesn't work, please do.


Sean


July 27, 2004
In article <ce4h8p$1nq7$1@digitaldaemon.com>, Kris says...
>
>Minor detail: You'll forgive me for not wishing to confuse the Interface Resolution issue with that of the peek-a-boo game ~ one cannot alias a super-class method to fulfill an interface contract. You are simple forced to stub & dispatch. At any level of complexity, these stubs become a real issue.

Well that sucks.  I hadn't realized that.  Is the same true with "using" in C++?

>Did you see what Regan proposed? <g>

I think I scanned it.  Better scroll back :)


Sean


July 27, 2004
On Mon, 26 Jul 2004 20:02:47 -0700, Walter wrote:

> "Derek Parnell" <derek@psych.ward> wrote in message news:ce4bb2$1liq$1@digitaldaemon.com...
[snip]

>>
>> I will readjust my thinking, of course, as I don't expect D will change in this respect ;-)
> 
> The only rule to remember here is that name lookup happens before overload resolution <g>.

Right! Thanks. It all makes sense now. Not good sense, not clever sense, but at least I know where the craziness lies now.

I'll go away now and write lot's of D code to see if it still seems wrong. Maybe I could get used to the sand in my shorts <g>

-- 
Derek
Melbourne, Australia
27/Jul/04 1:44:30 PM
July 27, 2004
On Mon, 26 Jul 2004 19:50:11 -0700, Walter <newshound@digitalmars.com> wrote:

>
> "Regan Heath" <regan@netwin.co.nz> wrote in message
> news:opsbrrs9pv5a2sq9@digitalmars.com...
>> Aren't you only 'overloading/overriding' if the function signature is
>> identical?
>
> No. The rule is the names are looked up first, *then* overload resolution
> happens.

I know what the rule is, all I'm saying is that you're not technically overloading unless the function signature is the same, you're supplying a specialisation. I was replying to the comment you made:

"The same applies to the overloading/overriding issue. It's designed to make such
unintentional mistakes unlikely - to overload based on methods from another
scope, you have to do it intentionally (using the alias declaration)."

I don't believe I am overloading or overriding below. Therefore I don't believe I should need to use alias.

> In your example below, abc is found in the current scope.
> oload1.abc is not found in the current scope, and therefore does not
> participate in function overload resolution.

I know.

>> Otherwise you're providing a specialisation i.e.
>>
>> [oload1.d]
>> module oload1;
>> void abc(int abc) {}
>>
>> [oload2.d]
>> module oload2;
>> import oload1;
>>
>> void abc(long abc) {}
>>
>> void main()
>> {
>> foo(1);
>> foo(1L);
>> }
>>
>> The above prints "long" twice, which isn't desired.
>>
>> The 'abc' provided by oload2 does _not_ override 'abc' provided by oload1
>> it's a different function signature.
>>
>> I agree that if it did override, it should be an error, one you could
>> catch at compile time, one that you could solve by using an alias to
>> specify the one you mean.
>>
>> Regan.
>>
>> --
>> Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
>
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 27, 2004
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opsbr73ixa5a2sq9@digitalmars.com...
> On Mon, 26 Jul 2004 19:50:11 -0700, Walter <newshound@digitalmars.com> wrote:
>
> >
> > "Regan Heath" <regan@netwin.co.nz> wrote in message news:opsbrrs9pv5a2sq9@digitalmars.com...
> >> Aren't you only 'overloading/overriding' if the function signature is identical?
> >
> > No. The rule is the names are looked up first, *then* overload
resolution
> > happens.
>
> I know what the rule is, all I'm saying is that you're not technically overloading unless the function signature is the same,

I think you mean "overriding" <g>.

> you're supplying a specialisation.

Specialization is the wrong word to use here, specialization really applies to templates, not functions. I admit the various jargons can be confusing - I think we understand each other, we're just not understanding each other's jargon.

> I was replying to the comment you made:
>
> "The same applies to the overloading/overriding issue. It's designed to
> make such
> unintentional mistakes unlikely - to overload based on methods from
another
> scope, you have to do it intentionally (using the alias declaration)."
>
> I don't believe I am overloading or overriding below. Therefore I don't believe I should need to use alias.
>
> > In your example below, abc is found in the current scope. oload1.abc is not found in the current scope, and therefore does not participate in function overload resolution.
>
> I know.
>
> >> Otherwise you're providing a specialisation i.e.
> >>
> >> [oload1.d]
> >> module oload1;
> >> void abc(int abc) {}
> >>
> >> [oload2.d]
> >> module oload2;
> >> import oload1;
> >>
> >> void abc(long abc) {}
> >>
> >> void main()
> >> {
> >> foo(1);
> >> foo(1L);
> >> }
> >>
> >> The above prints "long" twice, which isn't desired.
> >>
> >> The 'abc' provided by oload2 does _not_ override 'abc' provided by
> >> oload1
> >> it's a different function signature.
> >>
> >> I agree that if it did override, it should be an error, one you could catch at compile time, one that you could solve by using an alias to specify the one you mean.
> >>
> >> Regan.
> >>
> >> --
> >> Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
> >
> >
>
>
>
> -- 
> Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/