September 22, 2004 Re: overload bug - Re: MIID Mixins auto aliasing | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ant | In article <pan.2004.09.22.20.05.59.245040@yahoo.ca>, Ant says... > >this is nonsence, I expect the right function to be called, not the one that is "closer"... This discussion has been raging on this group for a while, but seems to have died down for now (and thank $deity for that :-) The issue is less clear cut and more complex than you probably realize at first glance, and both the Java way (which you are promoting) and the C++ way (the way it is now) have their pros and cons. Both can give you non-obvious and hard-to-catch bugs in certain cases. I personally prefer the way it is now, though, since it gives the option of "removing" inherrited members. If you want to the "correct" function to be called in your example, add # class B : A # { # alias A.func func; # ... # } (But you probably knew that?) >let's call it nonsence and convince Walter to change it. who can write a justification and present it on a PDF? Someone already tried that. It didn't work <g>. The author now calls himself antiAlias, IIRC. >Why do we have char converted to int in the first place? what is the justification (besides historical reasons?) Hmm, that's a good point. Some people are arguing that char should be something different from in C/C++ and Java. To make the difference more clear, maybe numeric manipulation of (w/d)chars should require an explicit cast? Nick |
September 22, 2004 Re: overload bug - Re: MIID Mixins auto aliasing | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ant | In article <pan.2004.09.22.20.05.59.245040@yahoo.ca>, Ant says... > >On Wed, 22 Sep 2004 18:40:14 +0000, Sean Kelly wrote: > >> In article <pan.2004.09.22.15.56.33.270961@yahoo.ca>, Ant says... >>> >>>if we replace b.func(int) by b.func(float) it's still called! >>>it's a bug. >> >> It's not a bug, it's how function visibility and overload resolution is handled >> in D (and in C++). > >this is nonsence, I expect the right function to be called, not the one that is "closer"... > >let's call it nonsence and convince Walter to change it. who can write a justification and present it on a PDF? I don't consider it nonsense. Consider this example (pulled from "The Design and Evolution of C++"): # class X { # int x; # public: # void copy( X p ) { x = p.x; } # } # # class XX : X { # int xx; # public: # void copy( XX p ) { xx = p.xx; X.copy( p ); } # } # # void f( X a, XX b ) { # a.copy( b ); // ok, copy X part of B # b.copy( a ); // error, copy(X) is hidden by copy(XX) # } "Allowing the second copy operation, as would happen if base and derived scopes were merged, would cause b's state to be partially updated. In most real cases, this would lead to very strange behavior of operations on XX objects." ie. the partial copy could result in a violation of class invariants and IMO is certainly undesired behavior. The visibility rules force the programmer to explicitly specify which functions won't do horrible things if they are made visible in the derived function's scope. >Why do we have char converted to int in the first place? what is the justification (besides historical reasons?) Consider this expression: short s = 1; int x = s * 5; Without implicit type promotion rules the only way this would be possible is with a cast: int x = cast(int) s * 5; I suppose it is arguable whether a D char should be treated the same as a C char with respect to promotion rules, but I don't have a major problem with it. >(I don't care how C++ does it (some might care)) Thing is, there is generally a good reason for how C++ does something. That reason may be buried in the annals of time, but that doesn't make it any less applicable today than it was 20 years ago. If you've got the will, I strongly recommend picking up "The Design and Evolution of C++" by Bjarne Stroustrup. The book covers pretty much every feature that was even considered for C++ and an explanation of why it was chosen/rejected, how the design changed over time, etc. If you want to know why something is the way it is, that's the best place I've found to look. Sean |
September 22, 2004 Re: overload bug - Re: MIID Mixins auto aliasing | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | On Wed, 22 Sep 2004 21:38:02 +0000, Sean Kelly wrote: > In article <pan.2004.09.22.20.05.59.245040@yahoo.ca>, Ant says... >> >>On Wed, 22 Sep 2004 18:40:14 +0000, Sean Kelly wrote: >> >>> In article <pan.2004.09.22.15.56.33.270961@yahoo.ca>, Ant says... >>>> >>>>if we replace b.func(int) by b.func(float) it's still called! >>>>it's a bug. >>> >>> It's not a bug, it's how function visibility and overload resolution is handled >>> in D (and in C++). >> >>this is nonsence, I expect the right function to be called, not the one that is "closer"... >> >>let's call it nonsence and convince Walter to change it. who can write a justification and present it on a PDF? > > I don't consider it nonsense. Consider this example (pulled from "The Design > and Evolution of C++"): [irrelevant example removed] [irrelevant OO discussion removed] <irrelevant> ??? this has nothing to do with the implicit conversion XX "is a" X but X is not a XX there is no confusion here, this is basic OO inheritance. and actually goes the other from the larger to the smaller. or from the specific to the general. </irrelevant> > >>Why do we have char converted to int in the first place? what is the justification (besides historical reasons?) > > Consider this expression: > > short s = 1; > int x = s * 5; > > Without implicit type promotion rules the only way this would be possible is with a cast: > > int x = cast(int) s * 5; that might be good. I don't know any language that strict. but in fact we are forgeting the real problem with D, consider this, where things really go wrong: ################################ class Color { void set(ubyte r,ubyte g,ubyte b) { // to set a color in GTK from 3 ubytes // some preprocessing must be executed printf("Color.set ubyte \n" ); } void set(int r,int g,int b) { printf("Color.set int \n" ); } } class ColorF : Color { void set(float r,float g,float b) { printf("ColorF.set float \n" ); } } void main() { ColorF c = new ColorF(); ubyte r = 1; ubyte g = 2; ubyte b = 3; c.set(r,g,b); } what should we expect? where's what we get: ################################# $ dmd Set.d -I~/dmd/src/phobos $ Set ColorF.set float ################################# where!, when! is that desirable? it's a bug! (0.91 clarified the method lookup resolution in the worst possible way) maybe the automatic conversion can exist on a strong type sensable language but only after the method look up with the full signature on the full class hierarchy. Ant |
September 22, 2004 Re: overload bug - Re: MIID Mixins auto aliasing | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ant | In article <pan.2004.09.22.22.16.54.963216@yahoo.ca>, Ant says... > >On Wed, 22 Sep 2004 21:38:02 +0000, Sean Kelly wrote: >> I don't consider it nonsense. Consider this example (pulled from "The Design >> and Evolution of C++"): > >[irrelevant example removed] >[irrelevant OO discussion removed] > ><irrelevant> >??? this has nothing to do with the implicit conversion >XX "is a" X >but X is not a XX >there is no confusion here, this is basic OO inheritance. >and actually goes the other from the larger to the smaller. >or from the specific to the general. ></irrelevant> Hardly irrelevant. If it were not for the lookup rules in D m(which mirror those in C++), your code would have worked as you intended it to. This is a two-pronged issue and I was addressing both. >but in fact we are forgeting the real problem with D, >consider this, where things really go wrong: >################################ >class Color >{ > void set(ubyte r,ubyte g,ubyte b) > { > // to set a color in GTK from 3 ubytes // some preprocessing must be > executed printf("Color.set ubyte \n" ); > } > void set(int r,int g,int b) > { > printf("Color.set int \n" ); > } >} > >class ColorF : Color >{ > void set(float r,float g,float b) > { > printf("ColorF.set float \n" ); > } >} > >void main() >{ > ColorF c = new ColorF(); > ubyte r = 1; > ubyte g = 2; > ubyte b = 3; > c.set(r,g,b); >} > >what should we expect? >where's what we get: > >################################# >$ dmd Set.d -I~/dmd/src/phobos >$ Set >ColorF.set float >################################# > >where!, when! is that desirable? >it's a bug! Assuming you expected it to print "Color.set ubyte" then this is the exact issue I was explaining above which you dismissed as "irrelevant." If you expected a compile-time error, then please offer a reason why implicit type promotion should not support ubyte to float conversions. And understand that this will likely impact any expression involving a ubyte and float value, not just overload resolution rules. Sean |
September 23, 2004 Re: overload bug - Re: MIID Mixins auto aliasing | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | On Wed, 22 Sep 2004 22:42:59 +0000, Sean Kelly wrote: > In article <pan.2004.09.22.22.16.54.963216@yahoo.ca>, Ant says... >>it's a bug! > > Assuming you expected it to print "Color.set ubyte" then this is the exact issue I was explaining above which you dismissed as "irrelevant." I still think it's different situations. > If you expected a > compile-time error, no, I expected the funct with the same name and paramter types to be called. I'm sorry if it was not clear. > then please offer a reason why implicit type promotion should not support ubyte to float conversions. I can accept that but I have a valid visible method with ubytes. I want that to be used. > And understand that this will > likely impact any expression involving a ubyte and float value, not just > overload resolution rules. yep, so let keep them but lookup the methods available correctly. D makes the inherited methods "second class" methods. Ant |
September 23, 2004 Re: overload bug - Re: MIID Mixins auto aliasing | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ant | On Wed, 22 Sep 2004 20:11:14 -0400, Ant <duitoolkit@yahoo.ca> wrote: > On Wed, 22 Sep 2004 22:42:59 +0000, Sean Kelly wrote: > >> In article <pan.2004.09.22.22.16.54.963216@yahoo.ca>, Ant says... >>> it's a bug! >> >> Assuming you expected it to print "Color.set ubyte" then this is the exact issue >> I was explaining above which you dismissed as "irrelevant." > > I still think it's different situations. It depends on how you look at it, it is a 2 part problem: - part 1, how methods are resolved. - part 2, implicit type casting. See the rules below for an explaination. >> If you expected a >> compile-time error, > > no, I expected the funct with the same name and paramter types to be called. > I'm sorry if it was not clear. I understand what you expected to happen, I've also expected the same thing... that was before I was told the method resolution rules and why they are the way they are. >> then please offer a reason why implicit type promotion >> should not support ubyte to float conversions. > > I can accept that but I have a valid visible method with ubytes. > I want that to be used. The crux of the matter is what 'visible' is defined as, in C/C++ and D it's not the same as in Java which I suspect has the behaviour you expect/want. >> And understand that this will >> likely impact any expression involving a ubyte and float value, not just >> overload resolution rules. > > yep, so let keep them but lookup the methods available correctly. > D makes the inherited methods "second class" methods. That is one way to look at it, yes. These are the method resolution rules detailed by Walter in a previous post: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/6978 <quote> How name lookup happens in a scope is a multi-stage process, each proceeding to the next if the name is not found in the current stage: 1) look for a member with the name 2) look in any imports *in this scope* 3) if current scope is a class scope, recursively look in base classes 4) repeat the process with the most enclosing scope I think it would be very strange to have base class symbols override imports in the current scope, i.e. if imports were looked up in some other scope than the one in which they were imported. </quote> So... D looks for a method name that matches (not taking into consideration the parameter(s) at all) when it finds one, it tries to implicitly cast what it has to what it needs to call that method, if this fails it gives an error. Java looks for a method name that matches, and it takes into consideration the parameter(s) meaning only a method taking the right parameters can match. The reason for D's behaviour is based on C/C++ behaviour, and they reason for that was detailed by Walter... <quote> Stroustrup gives two examples (slightly modified here): --------------------------------- class X1 { void f(int); } // chain of derivations X(n) : X(n-1) class X9: X8 { void f(double); } void g(X9 p) { p.f(1); // X1.f or X9.f ? } ----------------------------------- His argument is that one can easilly miss an overload of f() somewhere in a complex class heirarchy, and argues that one should not need to understand everything about a class heirarchy in order to derive from it. The other example involves operator=(), but since D doesn't allow overloading operator=() instead I'll rewrite it as if it were a function that needs to alter a class state, and a derived class written later that 'caches' a computation on the derived state: class B { long x; void set(long i) { x = i; } void set(int i) { x = i; } long squareIt() { return x * x; } } class D : B { long square; void set(long i) { B.set(i); square = x * x; } long squareIt() { return square; } } Now, imagine B were a complex class with a lot of stuff in it, and our optimizing programmer missed the existence of set(int). Then, one has: long foo(B b) { b.set(3); return b.squareIt(); } and we have an obscure bug. </quote> "Roberto Mariottini" tried Walters example above in Java, he found.. <Roberto Mariottini> I translated your example in Java, and it shows the "wrong" (non-C++) behaviour. The attached Test.java prints: The square is: 0 </Roberto Mariottini> So basically I can understand why you want/expect what you do, but I can also understand why it doesn't work that way. I dont think there is a perfect solution to this problem, and I am happy with the current one, it appears more robust to me. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
September 23, 2004 Re: overload bug - Re: MIID Mixins auto aliasing | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | On Thu, 23 Sep 2004 13:21:33 +1200, Regan Heath wrote: Ok, you convinced me that this is not going to change I'll shut up. Ant |
Copyright © 1999-2021 by the D Language Foundation