digitalmars.D - Three notable problems with method name resolution
- some idiot (413/413) Jul 23 2004 Attached is a small pdf noting three outstanding issues ~ each of which ...
- Andrew Edwards (4/12) Jul 23 2004 All viable points that undoubtedly needs attention. What's fascinating
- some idiot (4/16) Jul 23 2004 Don't follow Andrew; you imply there's some kind of hidden identity ...
- Kris (8/20) Jul 23 2004 Whoops! I see what you mean. That's what I get for posting from the lapt...
- J C Calvarese (8/15) Jul 23 2004 I knew who it was immediately. Even if it was PDF instead of a Word
- Kris (16/21) Jul 23 2004 There's always one more thing: forgot to mention that the required use o...
- Derek (52/58) Jul 23 2004 I must be using a different version of D, because the three issues you
- Ant (28/43) Jul 23 2004 you're wrong.
- Kris (39/52) Jul 23 2004 Firstly, I apologize for not providing working examples. In the interest...
- Lars Ivar Igesund (13/23) Jul 24 2004 I won't comment on the first two as I haven't tried to do such things.
- John Reimer (15/20) Jul 24 2004 I'll back Kris up on this one. It is most definitely an issue. The
- Derek (56/78) Jul 24 2004 Before I wrote my original response to this thread, I wrote some test
- John Reimer (16/77) Jul 24 2004 Ha! nobody would dare hint that you are simple. That's a good one :-).
- Walter (8/43) Jul 24 2004 I
- Kris (25/63) Jul 24 2004 Okay, so I screwed up the example slightly. Please permit me to rectify
- Derek (40/70) Jul 24 2004 I don't think that anybody is disagreeing with this position. Even Walte...
- Kris (7/18) Jul 24 2004 When I can't satisfy the Interface contract even with the mystical power...
- Andy Friesen (15/45) Jul 24 2004 The idea here, as I understand it, is that Bar is *re*implementing the
- Walter (55/58) Jul 24 2004 super-class
- Kris (39/90) Jul 25 2004 1) You'll forgive me Walter, for saying that I think you may just be
- Walter (37/72) Jul 25 2004 prototype
- Kris (10/12) Jul 25 2004 Ah ... right. There's a total disconnect here, since the original docume...
- parabolis (33/36) Jul 26 2004 Initially I was inclined to side with you here and suggest you simply
- Berin Loritsch (19/59) Jul 26 2004 I would expect this to not compile. For example, if you had two classes...
- parabolis (26/42) Jul 26 2004 Good point. Yes I did mean:
- Sean Kelly (22/58) Jul 26 2004 You have a recursive inheritance declaration with ReadingWriter. Not th...
- Kris (22/96) Jul 26 2004 class G : F
- Sean Kelly (14/31) Jul 26 2004 hehe... It was an example, after all. I imagine a real case would be mu...
-
Kris
(27/62)
Jul 26 2004
I would tend to agree with you regarding compilation Sean
. My view i... - parabolis (16/32) Jul 26 2004 I see your point and that would be a nasty bug to track down. In this
- Sean Kelly (17/29) Jul 26 2004 Well, all that's needed is an alias, not a full stub, but that's pretty ...
- Kris (20/36) Jul 26 2004 much the
- Sean Kelly (4/10) Jul 26 2004 I think I scanned it. Better scroll back :)
- Lars Ivar Igesund (7/17) Jul 27 2004 Yes, I would think so, but that is because C++ don't have interfaces,
- Sean Kelly (3/16) Jul 27 2004 Oops, of course. No wonder I had never run into it before.
- Sean Kelly (28/31) Jul 26 2004 Okay, I've modified my example a bit, but doing so has me reconsidering ...
- Regan Heath (24/47) Jul 26 2004 I think a new keyword is required to show the programmers intent. i.e.
- Blandger (24/41) Jul 26 2004 I think it's good example! Thanks Regan. I'm almost lost in this debates
- parabolis (36/40) Jul 26 2004 (Note this is a repost which corrects an example with a bug that crashes
- parabolis (97/103) Jul 26 2004 My understanding of what Kris wants is both
- Walter (13/30) Jul 26 2004 Yes, that's exactly the reason I gave. It's not a violation without a
- Walter (50/50) Jul 24 2004 You describe it as "The latter is utter nonsense, and smacks of either a...
- Sean Kelly (5/10) Jul 24 2004 Agreed. The resolution rules might be complex but I think they make per...
- Kris (10/21) Jul 24 2004 a
- J C Calvarese (68/103) Jul 24 2004 As I wrote in
- Kris (30/94) Jul 24 2004 If your referring to me, then yes; I do advocate such things. But in tho...
- J C Calvarese (36/98) Jul 24 2004 You asked for an explanation of "the benefits of those particular
- Kris (14/58) Jul 24 2004 those
- Walter (3/7) Jul 24 2004 That's a compiler bug.
- Walter (14/17) Jul 24 2004 resolution
- Kris (30/47) Jul 24 2004 looked
- Walter (76/116) Jul 25 2004 the
- Lars Ivar Igesund (9/54) Jul 26 2004 This is clearly bad design/programming of the class D. If you override
- Walter (15/22) Jul 26 2004 Of course - and that's the problem. It's an easy mistake to make, in my
- Regan Heath (26/51) Jul 26 2004 Aren't you only 'overloading/overriding' if the function signature is
- Walter (6/30) Jul 26 2004 No. The rule is the names are looked up first, *then* overload resolutio...
- Regan Heath (14/55) Jul 26 2004 I know what the rule is, all I'm saying is that you're not technically
- Walter (9/69) Jul 26 2004 resolution
- Regan Heath (74/100) Jul 27 2004 Either or, I used both above, you used both above in your original
- Lars Ivar Igesund (9/13) Jul 27 2004 I find it hard to follow your argumentation, probably due to the above
- Arcane Jill (9/13) Jul 27 2004 So you can have a function which both overloads and overrides at the sam...
- Regan Heath (11/23) Jul 27 2004 I mean't overriding. I now have a better understanding of the common
- Kris (22/40) Jul 26 2004 But yet again you fail to qualify why
- Derek Parnell (102/160) Jul 26 2004 [snip]
- stonecobra (17/65) Jul 26 2004 So, Walter, are you saying that alias is necessary to protect us from
- Andy Friesen (11/51) Jul 26 2004 C++ and C# do exactly the same thing, which suggests that overloading
- Arcane Jill (12/24) Jul 26 2004 I actually got caught out with this one a few years back - in C++. I tho...
- Walter (10/18) Jul 26 2004 thought the
- Walter (36/126) Jul 26 2004 That's normal behavior, it's the integral argument promotion rules in C ...
- Sean Kelly (13/58) Jul 26 2004 I like the current D scheme. In a sense, every class defines its own in...
- Regan Heath (29/102) Jul 26 2004 Requiring override protects you from doing this...
- Derek Parnell (35/181) Jul 26 2004 ...and 'normal' is equivalent to 'desirable', right? It seems wrong to m...
- Walter (18/49) Jul 26 2004 'double'
- Derek Parnell (10/18) Jul 26 2004 Right! Thanks. It all makes sense now. Not good sense, not clever sense,
- Arcane Jill (27/61) Jul 26 2004 Then one should RTFM. Java, of course, has a compiler which can automati...
- Daniel Horn (7/50) Jul 26 2004 But now you have turned a compile time bug into a run time bug
- Walter (19/67) Jul 26 2004 a
- Roberto Mariottini (22/29) Jul 26 2004 I translated your example in Java, and it shows the "wrong" (non-C++) be...
- Walter (7/18) Jul 26 2004 a
- Russ Lewis (25/103) Jul 26 2004 Once again, I find myself in the middle. Theoretically, I agree with
- Lars Ivar Igesund (34/60) Jul 25 2004 Sorry, but that example has little to do with overloading, but very much...
-
Walter
(4/8)
Jul 25 2004
I can concur with "badly documented"
but why is the way C++ has work... - h3r3tic (6/8) Jul 25 2004 The fact that everyone got used to it doesn't mean it's the best. If peo...
- Kris (20/29) Jul 25 2004 Lars made a series of valid points in his three emails Walter; as have m...
- Farmer (70/84) Jul 26 2004 I don't get it.
- Kris (36/80) Jul 26 2004 remain
- Farmer (57/81) Jul 27 2004 Kris, I see I can follow your thoughts, and you can follow mine:
- Lars Ivar Igesund (2/4) Jul 27 2004 Heh, funny.
- Arcane Jill (4/6) Jul 26 2004 Not wishing to be /too/ pedantic, but C++ came before Java. So by that
- Farmer (7/19) Jul 27 2004 Ops,
- Sha Chancellor (12/71) Jul 24 2004 I think his point has some validity to it. Importing should have a
- Sha Chancellor (3/17) Jul 24 2004 Pardon my stupidity, I meant to respond to external name resolution.
- Kris (22/72) Jul 24 2004 Thanks Walter;
- Walter (9/12) Jul 24 2004 1) I find Stroustrup's argument in the ARM 13.1 (outlined in another
- John Reimer (27/43) Jul 24 2004 As brilliant as he is, could Stroustrup actually be wrong on the matter?
- Walter (12/38) Jul 25 2004 Heaven knows I disagree with Dr. Stroustrup on many points. However, thi...
- Kris (7/10) Jul 25 2004 I am, huh? I thought I was advocating logical progression and continuity...
- Sean Kelly (6/14) Jul 25 2004 This discussion would probably be better continued once the associated c...
- Kris (21/37) Jul 25 2004 That would be a fair point Sean, but the issue is not about the bugs
- Lars Ivar Igesund (7/13) Jul 25 2004 IMHO, C++ is *not* the language you want to imitate when it comes to OOP...
- Regan Heath (14/61) Jul 25 2004 You should choose the one that best suits D. It appears you believe you
- Sha Chancellor (8/61) Jul 25 2004 If the alias thing is a bug, I disagree on all counts. I like the
- Walter (12/18) Jul 25 2004 That is another way to look at it. It can be a problem if one has an
- Lars Ivar Igesund (5/24) Jul 25 2004 The rule would still be straightforward if it was:
- Walter (6/12) Jul 25 2004 That's a good thought, but overload resolution is not pass/fail, it has
- Kris (9/23) Jul 25 2004 What you specifically avoid in your reply, Walter, is that an EXACT (yes...
- parabolis (42/46) Jul 28 2004 I have read what /feels/ like thousands of posts in which you
- Sean Kelly (10/15) Jul 27 2004 They are. But as I pointed out in another post, D is different from C++...
- parabolis (13/30) Jul 28 2004 That is good to hear. I am by no means an avid C++ programmer
- Kris (12/12) Jul 24 2004 Also, please note that following doesn't even compile:
- Sean Kelly (4/16) Jul 24 2004 I'd forgotten about this detail. And adding override doesn't help. Oka...
- J C Calvarese (31/47) Jul 24 2004 I'm not saying you're wrong on the broader issues (I'm still trying to
- Derek (11/27) Jul 24 2004 This is just a bug. If the sub-class has a method with the same signatur...
- Kris (7/34) Jul 24 2004 I don't think anyone suggested that particular one was anything else, De...
- Derek (9/13) Jul 24 2004 Sorry, it seemed to me that you were implying that this current behaviou...
- Walter (3/15) Jul 24 2004 And that is a compiler bug!
- parabolis (10/24) Jul 25 2004 I believe this example is misleading. The name resolution is important
- Walter (8/32) Jul 25 2004 an
- Vathix (28/33) Jul 24 2004 has
- Kris (14/28) Jul 24 2004 I
- Walter (8/16) Jul 24 2004 implement
- Kris (44/44) Jul 26 2004 I see some things that I'd like to clarify and expand upon, if I may:
- Walter (16/16) Jul 24 2004 Let me explain what is happening here.
- Kris (23/39) Jul 24 2004 in
- Walter (25/43) Jul 24 2004 issue
- John Reimer (8/21) Jul 24 2004 I'm satisfied with this solution. As long as forward reference issues c...
- Kris (25/68) Jul 25 2004 If you can't fix imports to act as though outer-scope methods have someh...
- Walter (11/26) Jul 25 2004 But
- Kris (27/35) Jul 25 2004 Once again, Walter; you appear to be deliberately ignoring the core issu...
- Charlie (5/52) Jul 25 2004 Very true, I tried compiling DFL with .94 ( or some such ) and it died w...
- Kris (651/656) Jul 24 2004 I'm somewhat loath to post this (for a number of reasons), but will anyw...
- Kris (7/30) Jul 24 2004 Dagnabit. I apologize: made a glaring typo ... will link here instead
Attached is a small pdf noting three outstanding issues ~ each of which has various bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise. begin 666 The Three Sins of D Name Resolution.pdf M.#D M(" V,3$ "C8Q,2 -C$Q(" S.#D M(" S,S, (#DT- M-B -C$Q(" U-38 "ET*96YD;V)J" HQ,2 P(&]B: I;"C<W." -S<X(" W M(" S,S, (#DT- M,S,*+T9I;'1E<B O1FQA=&5$96-O9&4*/CX*<W1R96%M"GC:G5A+D]LV$K[/ MK\ 1W!IQ"? =WW;B5&4/.615M0<[!XC$2$HD4LO'C)VM_/?M!T!2$G<RCEWV MN)Z4?+H9P&PPF)=>#X M=$RGE&SYP X.TWVZE$W+`LT.UTYXN\5O4M:0%LQK+XX8 $; YIAO]P(Z=!C^ M.K( ,*"0Z#W\$OS*7HS$1H4J+DN,V2=YQDT6U*YA7U'(QJ Y9[H=-4XS^0J" M2F\M6%, "- =-P[(2OD]_BA0UT*:!G79CV9O0UC.E?QQ(%5X*VF'-V1*OD)4 MXMC)X_]MXPR#K MWYX#S5Z&70X"+I*G(%'L\RN_I=YOZ,^-BB?A%(?>NL4*C2> *? 3>P(=K$ T M6T.BG?R-`J_LO"T*<&/J& VQT[DX<AMFM++B"O#Q0ONZG 13P%& "B,Z6<YY M!87 Y!BZL4(D9Z"?Z:R ) !M2+NV683A*QHG*M,/G!2<GJ)W"=JPDL_DB9;< M0]KY/%D&_](2#EV"XQGE7?IJNCJ<]=>A+KW^0%8=.J8$*^B#B J/0Z O%(*+ MRO%.4U.\+NR>FO',#D4A MSUK'"(2QV1PF7-;.C_!ELMA+= QP8R =*+4X;] Q+JLR%W^L=Z2GNJDN4WDK M=H9EU+QUO!"$P4<L[N(,8V(A]*QD8GZ'ZX++<^& LV1BEG (M',R;2"B+;1< MTG2\R-24/92EKG3\;J%SB=4,2_CFXJCX5^HRJN'1]T:88RVSU 0=A1'7/1/I M=DY Z": % 1EE &IK .*4N:J`LU5X(J;>C-!H,8^LW Z:N2?5XOA(29DMYUQ M _G-"B- P?EL?Q V!VLZK&-FH)'!$3EG 2O!7.5;[I+YJY%A.=BY3YY<N ?O M`0-809S IX'\=AI(\BA,1*JA]4EP((" GD[]X3CXR>1N?DBC[/H$\DIX.\CH M,"K8VNIDL+2!1AAX\=3B-4V-/ALA3 OT%BJAJ?*_%(PD3),D83I0BF%M$+H[ M+;M/OX :.Y%^F&5O2-EXJ:S\ ZR 6^,P*6*7ES?.^.%(:407/9'BLV-0_^_0 MV\O4U4Y=S6M+77]!KR7)%?MATQXM^[Q'\<VLI=,"\G16:ADU'YXW[-$Y/G%- MIYU*4\?\K=H`G,(LF>7-Z?#GJL0ZNCI+<T3J&G9JFM8)7W/+K $ZNZ\!M"?> M"+>(HP.4#PZ4ON^1\0X:*QDQJ S!DO*Z+UF.K 5I`)T!3=ENR'0] %F,SE?/ M8T)MP3K,E Y[FA[K<S[7Y_XOU42%3Z>N)A*V*$F9,[L&\O/I+8Z+KIE=P!^: MU+-SIYRDZV]W]V^/^)9*+Y<\BU3\I'?[F(G]);V)),6*`&K1(0<>N0_?C3 ` M6L4<`%PQEXLAC5.WOGBFXQUL8%_!K-_S2#J]YQ5NJ/*/WNZ]STUM;HJZ>IO& M"C8 ,"!O8FH*/#P M=&5N=', ,34 ,"!2"CX^"F5N9&]B: H*,3< ,"!O8FH*/#P*+TQE;F=T:" R M,3$W"B]&:6QT97( +T9L871E1&5C;V1E"CX^"G-T<F5A;0IXVJU868_;R!%^ MX1'9[*ZN_NKXJOIA???7C](&,ECO[M(H5S(/8OCG'O,XT/ 8K)_N/HE_5E^/ M4:+!-Y!=U"CF)=2YEWL,+6R\A^\RC44-VQCQA *J;< 'BD%'_I\$[1[/DMV" M2&59E*KIN=HJ-* J_MDZ<;2 !5V!HF,=968J`!7+<M&TH&XJWJ^25F:A4GEJ M0FU%5WV//D8M5CM]"*)SUQ/*FE^+OCS09^U0/U2(MEO1'4.3B#TCS-_/;84? MJ4V494&2V\C20413GUYN^J:T-&^<_DE$J VXS?I0]/28.$>]QS<97VD>.T\F M:)[)?OYX[O/F%-I4-)>.)&2BN!0OH<G%E4#M5TPPU".&M!Z,L NU&AUED"$G M,C!L-OC2]6U1PE<]R-Z0T*Y:E1!$8,RNPZ".// V,AY[Z[%_1/&Y^*R4 LD4 MF* ^AVH+X;.RR23^DES\<>8`9+4('E+Z!>,#Y\?BT%Q03(8?0 JX&!^HZ(\U M2(E!Y?-37-HC3N Q]&!E73S0#CQ. M(7MM R*HBR=DB"J Y9 #B M BA/XMRMXF= N20VD4TXB_P&;MSM7H[ 5X]U7[6[ IRT"GYM:HK(;M#B-<*T M61JIC$4]U >T8(7.:*=.5[L0819SF7&59CX9M,UYCWD:(F<&(N41&+R0>8SX MTK')JO^B"X!N)^9.#E5TIXY#O*DKMO^E.9_0I)H7&0$QB,DR,>RX4P=C9=#F MO/+)19N$$_+)),2,LQ8>B 4F<N*VR&^\6]-3+F)U6R*-+!'_PK=%"8/E!IZR MQO (9]P`7P8CN'<FG2P=8S#U4X^^W)%)?!LM_4-HI> C35VV55\YIB\IE9++ MR$DQD$T`S?/1NF_$5((Q96T>)>31HN/8N$G*6J50[HP+AEJ$-7<O;"A4KN"S MP!&V54F%8='"%DW-5E'B8]/2T^#B3PCM,^6WZMX3G\RC-%\RWYY0_$HPUT%_ MJ#KF_6.H`%S6($4-&*:BW 9.!1]K']Y=R6'\JR32OF*N^Q"(A^I+V Y)B,K, MD(KEJ:"BN*/L%2!XTIWX0_"(1H0AL\#SIH M.B6FT!K\:I5'$H(R:*L["<Y%Q?YNZ7D/ZV\YGTYR[$U<#S M..#NP0 M+0FEEK&H;;!$TU W<H$D%TQ+:V/Q4+0TS0Z-0D;9!\B),E%5CV7^R.P::OA- MX_*\>Y\E/6)0*.B)U(KC4+)1::RU=%U$7:+TRFFPZ%Y0O;)Y0F6?23E6ZT8M M</EN$S(]7B9TNT&!L:!':K_FB0Q*SS_.I$ +!H"?J0&ZZ'4Z]?T T,QQ0%FF M\JH?A#T)44F(9B.B4)/H`6P:9:/Q;0A]][X"P>TK(RQDZF:L&:R#EMO-5[U( M^HG%#UPC9 8*VD"E8RV[3&48C=]QI6!B**9G IQ6HUTCD$PMAH2*\/>*(35F MX&E,M$IB(:),%IE VRC]:8E6F1BQ_BZ6]]3Y4TGJ&T2ZS)M(I+$RKQ+I+69X MA0=^H#IY#P_,M7ZK,'B;!Z124>)H\.&,L9_9JTM*Y5JD35L5:!?NI20$[P6I M "J7+O!L?E4`0R!BPL.F[G>ZC4A<VT2*[ \]WPYLWN S>'O.0<_NA3*Z22;- M/O=#TH MG^E2&)XU4CP 3A1O1HI_HALH9O,3.?*7*N :EW8AS_X)_ ZLT IE;F1S=')E M94-=(#X M38O^]\Y-LNPX.1<$ 262& YGOOEF.)\>[CY\T8G2ZF%SEP6%T84*X4\>BU!% M^* >#G??O7^Z4]W7K;^*8J]1OC&>]G]6#W^[2^( U%D"WSU4=U[DJX=?[L+ M*/Y/5;?%7?)W=LFT"9*4MRGWUH\2K^]AH]!3GZP?IUZG?E)?6C_57NO'H7>O MOG[QC;Q,([ RR;R.=0K52 <ZT9IT^B_I% =)',<TD>L8)[Y[)S].6$)=P9D2 M;PU2M-<]>H^^>EO4Y=C_IC$31)')WI"\\5<F7JBL?F6/SP]W.C4JC=, ,BK6 M09:J51%H712J<W<:[!FB;3?7QO[T\*Z]26B4!WG.!N_'H_-CL%RP:6>CDG)_ M9N569+CHQI'?G EI1_:\X$L;&H,?\'A2 *\_\/.*7^ED]BSX[!K.S+3HS&F M1VUP*BV\VH\RKZG])/<&6*!YP.[]>%[2.5L.==O :US0,N.U,LEO.Q+0TXK0 M440&QFA.[?[D<#J7W5 M>?H98Z[M]E6 &QKOX\!;[9WM\3$->0DN3Q-O9T_TI-$'^TM(3Z?Y"D?HX. . MNV8"$N" '6$TGM[.&,D+;^U\$\F$Y8,="&2_X$Z$RTRF=[345K;<^>!NLGZ6 M"0J&HJD<N[XFMFID[%0CPUIZ2^0W]=;M"%CWHQ08#HPQDAKR MX<%V P^PJ!_7/NQ>DBLM,+YLGX1PP'%]&TAD5P=$45&T03 \P^:%>'M'\19. MIZ=#TC MYR58:[!.V38G$ $GCJ;U5N21 9BT>B<?]&!\&.5W,")91X-(.JC=$J9F;(-] M*U1W89D9%%_9F4OJ1&LWI. +VHA'GG=H:-><X0Y*]T,WEB DLV0G%9)R) A MPXX&2"Z/KH%T4. 3BIL^:*%.`<3U5[::4?1W1R;JP4NYMUAC`E-,:[[A;KO) M[X" JF7V2B>PN:4)#RCP2 M]O[$0!2-H)X4!CH!,NJ!5N(%16DC]J"X,R'8OW*K-<&B1?/"U+W(&9L&V<<! MX'JT .U>!%-GA2J1.3;/=/JNLV"*ZAT*LC7:$1,S?4!22LH$NI X P[U+M5J M3#SCMD<+W0N?,5LDF+;/_D7Z8%B=T-(,'6$VI PFGPT2L0"G;4 DY,8C&68D M8T&:GOBH=X/L*2)P"%A2DNGJ &F%G4H#V MH"6&A4.4EO.LZ"!LV#G>9<&T/$#PS>2%:P0$* #J\Q[1Y+:\8*H\; 'F7!A MJ'"^<[-<& /XDE/,51V#R4QX MOH4?SJI'<M2;9;DV:9#A=: ($BH+,<&]T)WC9 499T&4+I9_%X1PP/(S;AS/ MM-50-B%3K<J6!INALY <9^1!E$6<Z-*%O& N<V! 2S8XN46Q=U'HW',=W0./ MR"; 7&1$.(G[ =:O%"671::)!4PP=:""%Y,,U9D2$<O$[]1 ,U)\E1RC7$)< M9$> ETGG= ZA8,O2'0>J`"_B\-&$R3N0B-,XB%4<) &U$+Q/XW[?[^KA3V^B M AH;<JO[NI$L9L+BHFQ<7.G ;D35;IAZQQ'9)F?]2AD\UZ3DFUPB9WGI;(3L M64Y"M^YNA?X.V=_Z2 =[69+K\"J#U^>RL\C.<,8]KHE8YW S^_=(;NV )^'G M7,%IA.*M>%P6.<*EY+]EC8;D +>J?:763HT]Y:HH60""` 0^[4>!';T=Q^[8 M!;/QTLEX09&&A5B0GS%8PA">S^V:CWZ2>/O:]NKHW-/*KM9MJ_X*]R$DT+<= M`I),' 6I1-Z_X'+(.5Z2B.2F=I3DPC%P<HOD9"4U71,E)L/S/=#P/=!,ZX', MY*K]^HU:*UT].'3Y17-5>JBOFZO2"<0+U"I/SQ^KXXB$/ZA'#U >0?FG?OC MAKG1>-5!??OSD3)TBX9OMA02/_#Y2E M!*BL_^!9UB]H") $V+PA:C[-AP_*T>H2?K$ *^_5AL*(.K>=HH[Y?K]H9_=U MJ09*\4='[Z\;NY,W?UO[5H?YDA"(? C:8;B,X7!JSG":D"[CN8"$^?[HRAIM M"F5N9&]B: H*,3 ,"!O8FH*/#P M72 ^/ HO0V]N=&5N=', ,3D ,"!2"CX^"F5N9&]B: H*,2 P(&]B: H\/ HO M0V]U;G0 , H^/ IE;F1O8FH*"C, ,"!O8FH*/#P*+U1Y<&4 +T-A=&%L;V<* M;V)J"CP\"B],96YG=& ,C W- HO1FEL=&5R("]&;&%T941E8V]D90H^/ IS M=')E86T*>-K-65N/V\89?=]?P;X40\"B.;S3>;*3%'61)D4C( _9/G"E64E= MB61X67E1]+_WN\V0U&K7#NH"C1&+')(SW_6<,^,/ZYNW?]*II[WU_4T>E)$N M,M4=!N.GJ>J\=QZ,Y.$TPI:$WDH'.M6:+/D76?+]^D8G99!&7AYJ_-%A4'BK M,M"Z++W.W& P+$0C[R^M_K!^U7 =95Y6 O,%6WYI9#OZ4:8&[U8=:C_6</7) M3S-UZ[]L;!*D29+,'_RJWK[UMCA1XR<0C[[!J4ZTQ+ _^%&JZIT?:>5MZ>;> M9.N_+P*;I6F0%2ZP<?HU`IL4091\+K ??V[\-)=P?*P'YU"'$4A5A=<;0^Y" M\,.+X%N'_OO #PW ML^0X4(:7"\+(`9>H]WY<PD('! =\)U)FBU.DZH0?FV'?;,EF6/= 95P[;R(U MP:L!6I+('.Q++0%]0C^:$>]2ZVWWA$;A4%3*8 W-4*JQ-W;5+X?4*,VQ+],\ MF<JAIX!I"! $D /FHL.3=N8VBJ*>TU4WLD8_;O8<3FX<708EY IS%MN<G6AM MJ9DX*53UB*FJ#F MO87/SX2WU4!+Y5QU34<5:*=N[F E*O7?1CO*E<TE5>UX5)-E,40$[$BT^OW5 MD>1AD'AI%CGFPC(`OXBHD :^*/,)4%^VG$=BP &BO+6V>E=Q'.1:TI NTL!8 M,Y[YU)K-`, PT-=8$M"^U98&X$7I[WL,:',\(L V9V3G4NV\`TY5;S"X54T0 M3GY4PZ&IW_WN*".^1D60%/\[60,TF>H<(3S+P:BO1;TI$+FE7N*EXZ%"\.C1 MNC*]`A\MEL\X?./,C8(XCG+.\=>51<)P_T^R:$G'%]Z#F<3CP^;S'[[.UHE. M ERT^ ]FL- 'RAN<V50M7A<3Z,CM'9$ ,F*N-C26J9]^DH?"5B.U8<OE3MW8 MDRT% <[*&;_W"P)V8 Z4'E]2>B$+,:V($KG"U$A6)8(* $'!6*M%`&P-O E1 MU8J?CP<4OEMS79(TCZ;K",^V5 B(E6/;-AUR1JA$6YRYTCLC]S/=E"QUDTX2 MFW0/\#DT^#U=Y%094I]5+P])S1&7YNIZ<<AR!TRO-8D*!GB$\LA2H)Z4+U> MP;R!>Q><BDS;RMW6 /$9MQRG!B(CE<7"HJ;2HGS8&38;TU(Y7:L50(.V S22 MP 44+Y9?Q'J8GWR'/[)WJ(>.F=\*JS1VE81WJ"5K"D4#B:2R =JM&P=B!8(8 M?P(/]D.JHRW[N9-!PEE8HS<DQ]'^>RGRK> D1]=6`O;X$8>;:MMS<]F82DM? ML6OQF8H \-X?\9?V!:3 ()X[PU).H-6KT1ID\=LH3,4N(,S\V;Z$3B/B, EB MXDSU8<3_CL>?]X?A#T2X+_!LE&>.9_]L9(\AVT(!3:E:I$C8U'^\]QD/(-VN MP"#O$(M^CQC,&P/K:\-O'IWT/5T$ T7KQ>X)$B[,T/0CI3>),8- 48C"3&;\ M2^C!(?%BQBBB`EH![1E"4C_2/%3X97Y9O? ==/VF,P/Y`Z,;PNJ9^V$Y6S-> MKCEA)_2=<<U;7'+2BT651!K5=I3%02 "V7R"N-75D918A.8-!*9VCF<5EH8I M NBBB#U MB;D>WFT)./ (+>83,)UEZHY.=T0OLWX1/&=)E L%ZE2HN!JXQ?GX)8]<A*_% M9V1'Y(0&O\ACU#K0="4IIP0,?L/D/:D5L 0W]1FD\:%GI*3&!A\,U=-",^.D MV50(63G#QI9#SW&XW)FOJ/5!+].)`.E!%C$L4KCX- ]\-U5XQHSKWJ"HTM>K M.^ A++\M`[7SZ!H'LO75EBATVCU X7V[ZH<GQ$AWAH0R?.E5,?/*R4_T2KC: M<3?J0KA-%B$^KU_5WMP`WWE',J'>C?2[,UX/:0L<5&86*H,R"TO!2[X&6H9> M.B'5$;;A/KA"*HU#X7VGNUPG+H 8YRA TKXANAXO030J)XA#D^ 8<AZ]CA7$ M7=<\F!KM=:?UO'<WW4OR?MJN`")5W::B(PU1*5P^K :^HS" D&LQ/'A1+V ; MW!Q;,I<EA: :6!OS.-!).4M4+$>(PH^BAF*NXSB_/&6W^R<NX^;4^]R<;GQN M`8U,_6TE?]6VIL+PN+I_0;; *2 =12UK'^"=09DJGH"YR)9[[ L<STK!T)JQ M<]4]D/C+BR7F<7[Z 0[%=LP1A%W7BX?.K!%N[N2[P!W5 )[ZVQ'W[+"3,G** MPH V'4V%UG.W(]1Z[B>"BYG8:MI0SH\ S&(FKAV[A3E7>*)A<2W4\\VR.VJB M$UU *SK=Z =3`U5 :]M_JF+7Y <)O&)Z-6OH`'\AF^Z7- 5;!BELJ+M(0LBF M8V5S(#P M,"!O8FH*/#P*+U1Y<&4 +U!A9V5S"B]+:61S(%L*-B P(%(*,38 ,"!2"C$X M+U1Y<&4 +T9O;G1$97-C<FEP=&]R"B]!<V-E;G0 .#DQ M+U1I;65S3F5W4F]M86Y04TU4"CX^"F5N9&]B: H*,3 ,"!O8FH*/#P*+U1Y M,C .3 U70HO271A;&EC06YG;&4 , HO4W1E;58 , HO1F]N=$YA;64 +T%R M;6%N4%,M271A;&EC350*/CX*96YD;V)J" HQ-" P(&]B: H\/ HO5'EP92 O M<V-E;G0 +3(Q, HO1FQA9W, ,S(*+T9O;G1"0F]X(%LP("TR,3( ,C8V-2 Y M5 H^/ IE;F1O8FH*"C4 ,"!O8FH*/#P*+T8Q-0H\/ HO5'EP92 O1F]N= HO M4W5B='EP92 O5')U951Y<&4*+T)A<V5&;VYT("]4:6UE<TYE=U)O;6%N4%-- M4 H^/ HO1C$V"CP\"B]4>7!E("]&;VYT"B]3=6)T>7!E("]4<G5E5'EP90HO M0F%S949O;G0 +T%R:6%L+4)O;&1-5 HO16YC;V1I;F< +U=I;D%N<VE%;F-O M;W( ,3 ,"!2"B]7:61T:', .2 P(%(*/CX*+T8Q-PH\/ HO5'EP92 O1F]N M= HO4W5B='EP92 O5')U951Y<&4*+T)A<V5&;VYT("]4:6UE<TYE=U)O;6%N M4%,M271A;&EC350*+T5N8V]D:6YG("]7:6Y!;G-I16YC;V1I;F<*+T9I<G-T M("]4<G5E5'EP90HO0F%S949O;G0 +T%R:6%L350*+T5N8V]D:6YG("]7:6Y! M;G-I16YC;V1I;F<*+T9I<G-T0VAA<B P"B],87-T0VAA<B R-34*+T9O;G1$ M"G1R86EL97(*/#P*+U-I>F4 ,C(*+U)O;W0 ,R P(%(*+TEN9F\ ,B P(%(* (.38*)25%3T8` ` end
Jul 23 2004
some idiot wrote:Attached is a small pdf noting three outstanding issues ~ each of which has various bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.All viable points that undoubtedly needs attention. What's fascinating about this post is how you can almost identify the author simply by the message "he" sends. Interesting!
Jul 23 2004
Don't follow Andrew; you imply there's some kind of hidden identity ... "Andrew Edwards" <ridimz_at yahoo.dot.com> wrote in message news:cdsei9$1kh$1 digitaldaemon.com...some idiot wrote:hasAttached is a small pdf noting three outstanding issues ~ each of whichvarious bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.All viable points that undoubtedly needs attention. What's fascinating about this post is how you can almost identify the author simply by the message "he" sends. Interesting!
Jul 23 2004
Whoops! I see what you mean. That's what I get for posting from the laptop (under CA sunshine). Glad to know I'm consistent though! Or maybe you thought it was someone else? <g> "Andrew Edwards" <ridimz_at yahoo.dot.com> wrote in message news:cdsei9$1kh$1 digitaldaemon.com...some idiot wrote:hasAttached is a small pdf noting three outstanding issues ~ each of whichvarious bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.All viable points that undoubtedly needs attention. What's fascinating about this post is how you can almost identify the author simply by the message "he" sends. Interesting!
Jul 23 2004
Kris wrote:Whoops! I see what you mean. That's what I get for posting from the laptop (under CA sunshine). Glad to know I'm consistent though! Or maybe you thought it was someone else? <g>I knew who it was immediately. Even if it was PDF instead of a Word document (good call!). I think your points were good. Hopefully, they're quirks of the implementation that can be unquirked. -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Jul 23 2004
There's always one more thing: forgot to mention that the required use of alias regarding the peek-a-boo game doesn't compile for certain signatures: class Writer { void put (bit x){} void put (int x){} } class MyWriter : Writer { alias Writer.put put; void put (bit x){} } "function put conflicts with MyWriter.put" "some idiot" <fu bar.org> wrote in message news:cdsd5t$u5$1 digitaldaemon.com...Attached is a small pdf noting three outstanding issues ~ each of whichhasvarious bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.
Jul 23 2004
On Fri, 23 Jul 2004 18:16:30 -0700, some idiot wrote:Attached is a small pdf noting three outstanding issues ~ each of which has various bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.I must be using a different version of D, because the three issues you mention are not a problem in v0.95. The first one, referring to extern C functions do not produce any error messages. In fact, it compiles and runs just fine. The second, using interfaces, is also correctly working here. By correct, I mean that it fails in exactly the way you say it does, because that's what I was expecting it to do - fail. My understanding of an interface is that it is JUST a list of cuntions that must be implemented in the class that you specified with the interface name. Here is the code in your example: <code> interface IFoo { void foo (); } interface IBar { void bar (); } class Foo : IFoo { void foo () { } } class Bar : Foo, IFoo, IBar { void bar() { } } </code> The problem is with class Bar. Here you explictly say that it is derived from class Foo, and must implement interface IFoo and IBar. However, you have only got it implementing bar(). The foo() is implemented in Foo but not in Bar. You are obviously expecting implemented interfaces to be inherited. Now although the foo() function IS inherited by Bar, you have also said it must be *implemented* in Bar too, but you didn't implement it. In the third example, your Writer class does NOT implement any of the functions. And the MyWriter class only implements one of the functions, the one with (int). So when you try to call the function using (ulong) as an argument, the linker can't find any! This is exactly what I'd expect so I don't think taht D is in error here. Maybe you need to provide real implementation in the Writer class or else declare them as abstract functions. At least that way, you get a compiler error rather than a linker error. So maybe I don't really understand what the issues are. -- Derek Melbourne, Australia
Jul 23 2004
On Sat, 24 Jul 2004 15:32:51 +1000, Derek wrote:On Fri, 23 Jul 2004 18:16:30 -0700, some idiot wrote: I must be using a different version of D, because the three issues you mention are not a problem in v0.95.you're wrong the problems manifest on 0.95.The first one, referring to extern C functions do not produce any error messages. In fact, it compiles and runs just fine.you're wrong.The second, using interfaces, is also correctly working here.you're wrong. I have 1400 lines like: ddi/GC.d(61): class GC 1interface function OGTK.gtk is not implemented ddi/GC.d(61): class GC 1interface function OGTK.gtk is not implemented ddi/GC.d(61): class GC 1interface function OGTK.gtk is not implemented ddi/Screen.d(66): class Screen 1interface function OGTK.gtk is not implemented ddi/Screen.d(66): class Screen 1interface function OGTK.gtk is not implemented ddi/Screen.d(66): class Screen 1interface function OGTK.gtk is not implemented ddi/Visual.d(59): class Visual 1interface function OGTK.gtk is not implemented ddi/Visual.d(59): class Visual 1interface function OGTK.gtk is not implemented ddi/Visual.d(59): class Visual 1interface function OGTK.gtk is not implemented dui/AccelGroup.d(59): class AccelGroup 1interface function OGTK.gtk is not implemented none of those classes declares to implement the interface or is missing the method (as far as I can tell, you see 1400 lines...) just adding or removing "private import ddi.Pixbuf;" to class ddi.Value body makes the compiler produce or not those 1400 errors. (it's not a typo it one thousand and four hundred lines)My understanding of an interface is that it is JUST a list of cuntions that must be implemented in the class that you specified with the interface name.you're wrong.The problem is with class Bar. Here you explictly say that it is derived from class Foo, and must implement interface IFoo and IBar.the example is wrong.In the third example,alias is dumb for OO but D supports other paradigmas. examples? I posted enough already. Ant
Jul 23 2004
Firstly, I apologize for not providing working examples. In the interests of brevity the code was sliced and diced to occupy minimal space ~ inline for the rest: "Derek" <derek psyc.ward> wrote ...The first one, referring to extern C functions do not produce any error messages. In fact, it compiles and runs just fine.That's because (in the interests of brevity) I didn't attempt to make any references to the methods. Believe me, it's a problem we ran into with Mango (as were all these issues, and many more besides). I think you'll find several others will vouch for this also. There's a good writeup in the buglist if you care to look (6/10/2004).My understanding of an interface is that it is JUST a list of cuntionsthatmust be implemented in the class that you specified with the interface name.That's essentially correct, except for one thing: the class has only to satisfy the contract to be in compliance (otherwise it's a 'partial' implementation: like an abstract class). It does not matter how that contract is implemented! I'm tempted to repeat that. When you build something of significant complexity, the exposed interface (the contract) rarely matches the implementation in terms of inheritance, and nor should it! That's one of the true benefits of Interfaces. In D, you have to stub and dispatch all kinds of stuff to satisfy the compiler, or dispense with your nice clean inheritance-based design. It's very, very, messy. And rapidly becomes brittle as complexity increases. I'm not asking you to believe me Derek. Just build yourself something fairly complex using interfaces in D, and you'll run into this very quickly. Here's (a temporary link to) an older document written during the "Interface Wars" so you can get some additional history: http://svn.dsource.org/svn/projects/mango/trunk/doc/D%20Interfaces%20-%20v0.In the third example, your Writer class does NOT implement any of the functions. And the MyWriter class only implements one of the functions,theone with (int). So when you try to call the function using (ulong) as an argument, the linker can't find any! This is exactly what I'd expect so I don't think taht D is in error here. Maybe you need to provide real implementation in the Writer class or else declare them as abstract functions. At least that way, you get a compiler error rather than alinkererror.There's no need to shout mate ... I can 'hear' ya loud and clear <g> Again, that was just in the interests of brevity ... you have to understand that aspect of alias was added in a vague attempt to appease yet another problem exposed via Mango (in what I considered to be, and clearly expressed to Walter as a thorough hack). I'm afraid the examples were perhaps not as useful as I thought they were, although this was documented as a bug on several occasions. Why don't you try the one I posted a little earlier that doesn't even compile, and get back to me please? (fyi ~ I don't spend hours writing documents like those for fun ... it's a PITA)
Jul 23 2004
Derek wrote:In the third example, your Writer class does NOT implement any of the functions. And the MyWriter class only implements one of the functions, the one with (int). So when you try to call the function using (ulong) as an argument, the linker can't find any! This is exactly what I'd expect so I don't think taht D is in error here. Maybe you need to provide real implementation in the Writer class or else declare them as abstract functions. At least that way, you get a compiler error rather than a linker error. So maybe I don't really understand what the issues are.I won't comment on the first two as I haven't tried to do such things. The third problem is very real. Kris' example might not have implementations, but that's just for brevity (I suspect) as it really don't work for implemented functions. The workaround hack is incredibly unintuitive (and quite stupid) making D somewhat less of an OO language. The fact that it is only documented on the declarations page, just adds to the silliness of it all. How is _ANYONE_ coming to the language going to guess this? I flagged this as bug (together with many others) because I didn't know of the alias hack and got a system shock when I found out that it was intended behaviour. It is really a 'break' feature in a potential 'make or break' review of D. Lars Ivar Igesund
Jul 24 2004
On Sat, 24 Jul 2004 15:32:51 +1000, Derek wrote:I must be using a different version of D, because the three issues you mention are not a problem in v0.95. The first one, referring to extern C functions do not produce any error messages. In fact, it compiles and runs just fine.I'll back Kris up on this one. It is most definitely an issue. The example may compile fine as is, and that's part of the problem! Nobody sees the error until much later. Just go try to call a FileConduit instance's close() or read( char[] dst ) from another module, class, main, or whatever. You should quickly find that these methods no longer exist due to the miraculous effects of privately importing (internal to the class) std.c.linux.linux "close" and "read." These imported functions completely hide the classes close and read methods with no hope of recovery. DMD doesn't even attempt to overload these methods. Instead it rudely ends with a compile error message grumbling confusingly about incorrect arguments. The hapless programmer, not realizing what the import is doing, looks back in the code and is thoroughly confused at trying to figure out why his method calls are not valid even though they match the signatures in the class perfectly. This problem is definitely real.
Jul 24 2004
On Sat, 24 Jul 2004 00:41:15 -0700, John Reimer wrote:On Sat, 24 Jul 2004 15:32:51 +1000, Derek wrote:Before I wrote my original response to this thread, I wrote some test programs to try and understand what the issues were. I based my response on those test programs. As I've now had a number of people come back and tell me I'm dead wrong (and possibly a bit simple too), I guess I really do not understand the issues. Anyhow, here are the three files I made to test the "extern C/private import" issue. <file: test3.d> extern (C) { int read (int, void*, int); int close (int); } <end of file> <file: test4.d> class Conduit { abstract void close (); abstract void read (char[] dst); } class FileConduit : Conduit { private import test3; private int handle; void close () { printf("FileConduit Close\n"); test3.close (handle); } void read (char[] dst) { test3.read (handle, dst, dst.length); } } <end of file> <file: test2.d> import test4; void main() { FileConduit f = new FileConduit; f.close(); } <end of file> <compile and run results> G:\temp>dmd test2 test4 test3 F:\DMD\BIN\..\..\dm\bin\link.exe test2+test4+test3,,,user32+kernel32/noi; G:\temp>test2 FileConduit Close G:\temp> <end of run> What haven't I understood? -- Derek Melbourne, AustraliaI must be using a different version of D, because the three issues you mention are not a problem in v0.95. The first one, referring to extern C functions do not produce any error messages. In fact, it compiles and runs just fine.I'll back Kris up on this one. It is most definitely an issue. The example may compile fine as is, and that's part of the problem! Nobody sees the error until much later. Just go try to call a FileConduit instance's close() or read( char[] dst ) from another module, class, main, or whatever. You should quickly find that these methods no longer exist due to the miraculous effects of privately importing (internal to the class) std.c.linux.linux "close" and "read." These imported functions completely hide the classes close and read methods with no hope of recovery. DMD doesn't even attempt to overload these methods. Instead it rudely ends with a compile error message grumbling confusingly about incorrect arguments. The hapless programmer, not realizing what the import is doing, looks back in the code and is thoroughly confused at trying to figure out why his method calls are not valid even though they match the signatures in the class perfectly. This problem is definitely real.
Jul 24 2004
Before I wrote my original response to this thread, I wrote some test programs to try and understand what the issues were. I based my response on those test programs. As I've now had a number of people come back and tell me I'm dead wrong (and possibly a bit simple too), I guess I really do not understand the issues.Ha! nobody would dare hint that you are simple. That's a good one :-). Your point of view is appreciated. You obviously got some tough grit to wrangle on these issues against multiple opposing opinions. In fact you've generated a good example that I'll have to think about. One problem is that the situation in mango still generates the compiler error that I'm referring too despite your example's apparent revelation of the problem's non-existence. So somehow, the slightly more complicated example does what yours is not doing. Walter seems to have already described why this issue even comes up. So I assume it's existence is formally accepted already (but the argument is that there is a good reason for it's existence, such that it's not an important issue). As for your example, I'll have to figure what's going on differently between mango and it. Many pardons if I made out that this is an obvious case. Obviously it's not as obvious as I obviously thought! ;-)Anyhow, here are the three files I made to test the "externC/privateimport" issue. <file: test3.d> extern (C) { int read (int, void*, int); int close (int); } <end of file> <file: test4.d> class Conduit { abstract void close (); abstract void read (char[] dst); } class FileConduit : Conduit { private import test3; private int handle; void close () { printf("FileConduit Close\n"); test3.close (handle); } void read (char[] dst) { test3.read (handle, dst, dst.length); } } <end of file> <file: test2.d> import test4; void main() { FileConduit f = new FileConduit; f.close(); } <end of file> <compile and run results> G:\temp>dmd test2 test4 test3 F:\DMD\BIN\..\..\dm\bin\link.exe test2+test4+test3,,,user32+kernel32/noi; G:\temp>test2 FileConduit Close G:\temp> <end of run> What haven't I understood?
Jul 24 2004
"Derek" <derek psyc.ward> wrote in message news:h0kf8z2x9zvu.tyujz7z737ln$.dlg 40tude.net...The second, using interfaces, is also correctly working here. By correct,Imean that it fails in exactly the way you say it does, because that's what I was expecting it to do - fail. My understanding of an interface is that it is JUST a list of cuntionsthatmust be implemented in the class that you specified with the interface name. Here is the code in your example: <code> interface IFoo { void foo (); } interface IBar { void bar (); } class Foo : IFoo { void foo () { } } class Bar : Foo, IFoo, IBar { void bar() { } } </code> The problem is with class Bar. Here you explictly say that it is derived from class Foo, and must implement interface IFoo and IBar. However, you have only got it implementing bar(). The foo() is implemented in Foo but not in Bar. You are obviously expecting implemented interfaces to be inherited. Now although the foo() function IS inherited by Bar, you have also said it must be *implemented* in Bar too, but you didn't implementit. You're correct, it is deliberately designed to work this way. To get it to work the other way, just rewrite Bar as: class Bar : Foo, IBar
Jul 24 2004
Okay, so I screwed up the example slightly. Please permit me to rectify that: interface IFoo { void foo (); } interface IBar { void bar (); } class Foo { void foo (){} } class Bar : Foo, IFoo, IBar { void bar() {} } There have been reasons indicated as to why one would want to include super-class methods as part of a contract exposed by a sub-class. There hasn't yet been a single one to the contrary ... How about it Walter? I'd really, really, like to understand why super-class methods are explicitly denied from satisfying a sub-class contract. At least then there'd be something to discuss vis-a-vis pro & con ... - KrisHere is the code in your example: <code> interface IFoo { void foo (); } interface IBar { void bar (); } class Foo : IFoo { void foo () { } } class Bar : Foo, IFoo, IBar { void bar() { } } </code> The problem is with class Bar. Here you explictly say that it is derived from class Foo, and must implement interface IFoo and IBar. However, you have only got it implementing bar(). The foo() is implemented in Foo but not in Bar. You are obviously expecting implemented interfaces to be inherited. Now although the foo() function IS inherited by Bar, you have also said it must be *implemented* in Bar too, but you didn't implementit. You're correct, it is deliberately designed to work this way. To get it to work the other way, just rewrite Bar as: class Bar : Foo, IBar
Jul 24 2004
On Sat, 24 Jul 2004 10:47:15 -0700, Kris wrote:Okay, so I screwed up the example slightly. Please permit me to rectify that: interface IFoo { void foo (); } interface IBar { void bar (); } class Foo { void foo (){} } class Bar : Foo, IFoo, IBar { void bar() {} } There have been reasons indicated as to why one would want to include super-class methods as part of a contract exposed by a sub-class. There hasn't yet been a single one to the contrary ...I don't think that anybody is disagreeing with this position. Even Walter ;-)How about it Walter? I'd really, really, like to understand why super-class methods are explicitly denied from satisfying a sub-class contract. At least then there'd be something to discuss vis-a-vis pro & con ...<pedantic_mode> D does not *explicitly* deny super-clas methods from being exposed in a subclass. It *implicitly* denys them. To explicitly deny, one would have to add code to do that. However, it happens by *not* adding code, thus it is implicit. </pedantic_mode> SmallTalk, is not <insert your favorite OO lang here>. D allows the coder to satisfy a sub-class contract, but you have to do it explicitly. It is not done automatically for you. Why? Dunno. But that's the way of D ( and Walter). Okay so Java does it for you --- good on ya, Java! But this is D. class Bar : Foo, IFoo, IBar { void bar() {} } The way that I translate this definition is like this ... Bar is a class that is derived from Foo, and must implement the methods listed in IFoo, and must implement the methods listed in IBar. Because it is derived from Foo, any methods implemented in Bar that have the same signature as those in Foo, will override the Foo methods. If I wish users of Bar to access Foo methods, I must explicitly name those methods in Bar. In the code above, Bar implements all the IBar methods but does not implement any of the IFoo methods. Therefore it is in error. In D, one way of doing this is ... class Bar : Foo, IFoo, IBar { void bar() {} void foo() {Foo.foo();} } Yes, it is verbose having to write all this stuff. So maybe the approach to Walter should be along the lines of ... "Hey Walter, how can you get D to help us out here? We would like to avoid all this tedious and error-prone tasks, and thus make it easier for coders?" -- Derek Melbourne, Australia
Jul 24 2004
"Derek" wrote ...<pedantic_mode> D does not *explicitly* deny super-clas methods from being exposed in a subclass. It *implicitly* denys them. To explicitly deny, one would havetoadd code to do that. However, it happens by *not* adding code, thus it is implicit. </pedantic_mode>When I can't satisfy the Interface contract even with the mystical power of 'alias', I consider it an explicit denial. You are certainly welcome to your particular interpretation too :-)Yes, it is verbose having to write all this stuff. So maybe the approachtoWalter should be along the lines of ... "Hey Walter, how can you get D to help us out here? We would like to avoid all this tedious and error-prone tasks, and thus make it easier for coders?"I tried that approach on April 8th. Perhaps he'll listen to you instead <g>
Jul 24 2004
Kris wrote:Okay, so I screwed up the example slightly. Please permit me to rectify that: interface IFoo { void foo (); } interface IBar { void bar (); } class Foo { void foo (){} } class Bar : Foo, IFoo, IBar { void bar() {} } There have been reasons indicated as to why one would want to include super-class methods as part of a contract exposed by a sub-class. There hasn't yet been a single one to the contrary ... How about it Walter? I'd really, really, like to understand why super-class methods are explicitly denied from satisfying a sub-class contract. At least then there'd be something to discuss vis-a-vis pro & con ...The idea here, as I understand it, is that Bar is *re*implementing the IFoo interface, and so much explicitly define those methods declared in the interface. What I don't understand is why it would be useful to do so. Secondly, it leads me to think that, perhaps, Bar implements IFoo *twice*. But then I have to wonder why we would want to do this and how we are to state which IFoo we want to access. This second reason is probably, I think, the most important reason the current behaviour should be changed: it doesn't mean what a stupid person (hello!) thinks it means at first glance. Implementing an interface should just be a contractual obligation that the class define all the methods specified therein, wherever the definition. (abstract or what have you) -- andy
Jul 24 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu77l$158f$1 digitaldaemon.com...How about it Walter? I'd really, really, like to understand whysuper-classmethods are explicitly denied from satisfying a sub-class contract. Atleastthen there'd be something to discuss vis-a-vis pro & con ...Sure. D originally worked the way you suggest. However, this message to me by Joe Battelle convinced me otherwise. It's a bit complicated, but essentially it's to close up a type hole: -------------------------------------------- The fact that interfaces are snapshots and not inherited from class to subclass can really mess you up sometimes. Just tacking on the interface at each level in the hierarchy doesn't work either--you get a unique interface each time. Casting to a superclass before casting to the interface that the derived type supports can alter which version of the interface is called. The spec doesn't say much about this. Are we stuck with this feature of interfaces or will they be inheritable at some point? Example code: ------------- import c.stdio; interface D { abstract int foo(); } class A : D { int foo() { return 1; } } class B : A, D { //carry the D's, 'cause they're not inherited //this should tell you something's up :) //A's foo is taken to satisfy D. //a cast(D) on a B will always use this foo //even if the B is actually a further derived type with overloaded foo() } class C : B, D { int foo() { return 2; } } int main (char[][] args) { C c = new C; A a = (A) c; int j = a.foo(); // 2 B b = (B) c; int k = b.foo(); // 2 D d1 = (D) c; int l = d1.foo(); // 2 D d2 = (D) b; int m = d2.foo(); // 1 Gotcha!!! b.foo() not equal to (D)b.foo() //prints 2 2 2 1 printf("%d %d %d %d", j, k, l, m); return 0; } ---------------------------------------------------------------
Jul 24 2004
"Walter" wrote .Sure. D originally worked the way you suggest. However, this message to me by Joe Battelle convinced me otherwise. It's a bit complicated, but essentially it's to close up a type hole:1) You'll forgive me Walter, for saying that I think you may just be mistaken in terms of the time period. Recall that you sent me the prototype Interface-enabled D compiler (other than COM), and it most certainly did not have this "Contract Resolution" ability enabled. 2) the example below makes a comment about Interfaces not being inherited. In D they *are* inherited! I've used that time and time again to work around the ever-persistent "diamond interface" related bugs. 3) the example below is built explicitly to circumvent /some/ type system. Also, it /could/ be argued that the example below produces a valid and predictable result. Regardless, Because D interfaces *are* inherited this is quite possibly a moot point entirely. 4) Do you not think this supposed type hole can be worked out in some other way? The trade-off is, well, I've already documented all the fallout from this decision. 5) While not wishing to harp on about Java ~ if this is such a problem, how does Java avoid it? It manages perfectly well, thank-you-very-much. D is so supposed to be so much better, right? This "decoupled contract" aspect is a major player in the Interface arsenel: please do not underestimate it. Here's an extract from my revised document: "An Interface is nothing more than a contract. One of the great things about this notion is there's no implicit binding between the Interface and how it is actually fulfilled by the implementation. It is perfectly legitimate for a class to satisfy its contractual obligation in any way it sees fit; including via local methods, via public methods exposed through inheritance, via some base class, via an implemented abstract class, or any combination thereof. That is, the contract can be declared and fulfilled entirely by any particular class, aggregated piecemeal through inheritance, or be inherited itself through some super-class derivation. To stipulate otherwise would enforce an implementation restriction that has no bearing whatsoever upon the contract itself. Under those terms, satisfying the contract would mean ensuring the design of your exposed class hierarchy matches exactly that of the Interface hierarchy - thus negating the intentionally decoupled nature of the contract." Sorry Walter; there's just too many flaws in your statement to be convincing. - Kris-------------------------------------------- The fact that interfaces are snapshots and not inherited from class to subclass can really mess you up sometimes. Just tacking on the interface at each level in the hierarchy doesn't work either--you get a unique interface eachtime.Casting to a superclass before casting to the interface that the derived type supports can alter which version of the interface is called. The spec doesn't say much about this. Are we stuck with this feature of interfaces or will they be inheritableatsome point? Example code: ------------- import c.stdio; interface D { abstract int foo(); } class A : D { int foo() { return 1; } } class B : A, D { //carry the D's, 'cause they're not inherited //this should tell you something's up :) //A's foo is taken to satisfy D. //a cast(D) on a B will always use this foo //even if the B is actually a further derived type with overloaded foo() } class C : B, D { int foo() { return 2; } } int main (char[][] args) { C c = new C; A a = (A) c; int j = a.foo(); // 2 B b = (B) c; int k = b.foo(); // 2 D d1 = (D) c; int l = d1.foo(); // 2 D d2 = (D) b; int m = d2.foo(); // 1 Gotcha!!! b.foo() not equal to (D)b.foo() //prints 2 2 2 1 printf("%d %d %d %d", j, k, l, m); return 0; } ---------------------------------------------------------------
Jul 25 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdvo13$1srb$1 digitaldaemon.com...1) You'll forgive me Walter, for saying that I think you may just be mistaken in terms of the time period. Recall that you sent me theprototypeInterface-enabled D compiler (other than COM), and it most certainly didnothave this "Contract Resolution" ability enabled.At some point it must have worked that way, otherwise Joe wouldn't have sent me that message <g>.2) the example below makes a comment about Interfaces not being inherited. In D they *are* inherited! I've used that time and time again to workaroundthe ever-persistent "diamond interface" related bugs. 3) the example below is built explicitly to circumvent /some/ type system. Also, it /could/ be argued that the example below produces a valid and predictable result. Regardless, Because D interfaces *are* inherited thisisquite possibly a moot point entirely.The way interfaces have worked has changed around a bit, some of it was in response to Joe's emails to me. Interface semantics have several subtleties that escaped me early on <g>. In any case, what it used to do way back is not so important, what it does now is, and the type hole would exist if the inheritance rules would change. While it certainly would be predictable, so are the other scoping/resolution rules that you argue are incorrect <g>. I think this type hole is in the category of ones like: class A{} class B:A{} B[] b; foo(A[]); foo(b); which is disallowed. It's better to issue an error when a potential type hole exists, requiring a cast to resolve it, than to silently open such a hole and one's program inexplicably crashes.4) Do you not think this supposed type hole can be worked out in someotherway? The trade-off is, well, I've already documented all the fallout from this decision.Why is simply omitting the redundant interface name in the inheritance list a problem? I don't get it.5) While not wishing to harp on about Java ~ if this is such a problem,howdoes Java avoid it? It manages perfectly well, thank-you-very-much. D issosupposed to be so much better, right? This "decoupled contract" aspect isamajor player in the Interface arsenel: please do not underestimate it. Here's an extract from my revised document: "An Interface is nothing more than a contract. One of the great thingsaboutthis notion is there's no implicit binding between the Interface and howitis actually fulfilled by the implementation. It is perfectly legitimatefora class to satisfy its contractual obligation in any way it sees fit; including via local methods, via public methods exposed throughinheritance,via some base class, via an implemented abstract class, or any combination thereof. That is, the contract can be declared and fulfilled entirely byanyparticular class, aggregated piecemeal through inheritance, or beinheriteditself through some super-class derivation. To stipulate otherwise would enforce an implementation restriction thathasno bearing whatsoever upon the contract itself. Under those terms, satisfying the contract would mean ensuring the design of your exposedclasshierarchy matches exactly that of the Interface hierarchy - thus negating the intentionally decoupled nature of the contract." Sorry Walter; there's just too many flaws in your statement to be convincing.
Jul 25 2004
"Walter" <newshound digitalmars.com> wrote in messageWhy is simply omitting the redundant interface name in the inheritancelista problem? I don't get it.Ah ... right. There's a total disconnect here, since the original document had an error in it. I guess you didn't get a chance to see the various posts regarding clarification. Please take a look at this revised version, and let's pick up again after that? Thanks, and sorry about the misdirection. The example and grayed-text contained within should hopefully clarify what the issue is ... if not, I'll try to devise an alternate way to state it. http://svn.dsource.org/svn/projects/mango/trunk/doc/Names.pdf - Kris
Jul 25 2004
Walter wrote:Why is simply omitting the redundant interface name in the inheritance list a problem? I don't get it.Initially I was inclined to side with you here and suggest you simply make it an error to include a redundant interface name and finally put the matter to rest. However it is not that simple. Consider: ================================ interface Reads { void readSomething(); } interface Writes { void writeSomething(); } interface ReadsWrites { void readSomething(); void writeSomething(); } class Reader : Reads { void readSomething() { printf( "read1()" ); } } class Writer : Writer{ void writeSomething() { printf( "write1()" ); } } class WritingReader : Reader, ReadingWriter { void writeSomething() { printf( "write2()" ); } } class ReadingWriter : Writer, ReadingWriter { void readSomething() { printf( "read2()" ); } } ================ There are no redundant interfaces in this example and yet ReadingWriter and WritingReader are not considered valid implementations. BUG NOTE!!! The above code crashes the compiler when I try to compile it so you may want to note this as a bug. (win32 version)
Jul 26 2004
parabolis wrote:Walter wrote:I would expect this to not compile. For example, if you had two classes that referred to each other in the extends/implements area, then you would have a circular reference. This is really bad. All inheritance structures should follow a DAG (Directed Acyclic Graph), and there are all kinds of ways of detecting them, etc. For now, I have to assume that you meant to write ReadsWrites in place of ReadingWriter in the extends/implements area of the last two classes. If it does not compile in this case, I would be inclined to agree with you. I do realize that D is not Java, but it does seem very cumbersome to me to see a class have all methods necessary for an interface through inheritance, but it doesn't compile or run correctly. Question: wouldn't it be equally valid to have this: interface ReadsWrites : Reads, Writes {} wich would in turn have the readSomething() and writeSomething() methods inherited from the super-interfaces? include pure virtual abstract classes as interfaces, in C++).Why is simply omitting the redundant interface name in the inheritance list a problem? I don't get it.Initially I was inclined to side with you here and suggest you simply make it an error to include a redundant interface name and finally put the matter to rest. However it is not that simple. Consider: ================================ interface Reads { void readSomething(); } interface Writes { void writeSomething(); } interface ReadsWrites { void readSomething(); void writeSomething(); } class Reader : Reads { void readSomething() { printf( "read1()" ); } } class Writer : Writer{ void writeSomething() { printf( "write1()" ); } } class WritingReader : Reader, ReadingWriter { void writeSomething() { printf( "write2()" ); } } class ReadingWriter : Writer, ReadingWriter { void readSomething() { printf( "read2()" ); } }
Jul 26 2004
Berin Loritsch wrote:For now, I have to assume that you meant to write ReadsWrites in place of ReadingWriter in the extends/implements area of the last two classes. If it does not compile in this case, I would be inclined to agree with you.Good point. Yes I did mean: class WritingReader : Reader, Writes { void writeSomething() { printf( "write2()" ); } } class ReadingWriter : Writer, Reads { void readSomething() { printf( "read2()" ); } } Even with the change the the compiler still crashes.I do realize that D is not Java, but it does seem very cumbersome to me to see a class have all methods necessary for an interface through inheritance, but it doesn't compile or run correctly. Question: wouldn't it be equally valid to have this: interface ReadsWrites : Reads, Writes {} wich would in turn have the readSomething() and writeSomething() methods inherited from the super-interfaces?This compiles: interface Reads { void readSomething(); } interface Writes { void writeSomething(); } interface ReadsWrites : Reads, Writes {} As for whether I would use that instead... I think it depends on the sort of code you are writing. When writing library or large app code the Reads and Writes interfaces could be in different files and/or directories. The way I did it saves having to hunt for the source files and or docs to get the return type and function parameters. However code written for a smaller task would probably view interfaces as clutter and want to make them as terse as possible. Of course for that reason the code is unlikely to even use interfaces.
Jul 26 2004
In article <ce3rao$1g1s$1 digitaldaemon.com>, parabolis says...Walter wrote:You have a recursive inheritance declaration with ReadingWriter. Not that dmd should crash on it, but I suspect this is why :) Assuming you meant WritingReader for the second definition then you've still got a circular inheritance heirarchy which is not allowed. All that aside, should this really be legal? interface I { void foo( char x ); } class A { void foo( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E, I { void foo( int x ) {} } Assume that all the above classes have very long definitions and that A, B, and C are in a third-party library with no documentation and convoluted, badly formatted import files. As the creator of F I may very well have intended to define F.foo as the implementation for I.foo and just screwed up the prototype. With the existing lookup scheme this is flagged as an error but with the proposed scheme it would compile just fine. Further assume that A.foo is for some completely different purpose as A may have no knowledge of interface I. IMO the proposed scheme will be the cause of some very hard to find bugs. SeanWhy is simply omitting the redundant interface name in the inheritance list a problem? I don't get it.Initially I was inclined to side with you here and suggest you simply make it an error to include a redundant interface name and finally put the matter to rest. However it is not that simple. Consider: ================================ interface Reads { void readSomething(); } interface Writes { void writeSomething(); } interface ReadsWrites { void readSomething(); void writeSomething(); } class Reader : Reads { void readSomething() { printf( "read1()" ); } } class Writer : Writer{ void writeSomething() { printf( "write1()" ); } } class WritingReader : Reader, ReadingWriter { void writeSomething() { printf( "write2()" ); } } class ReadingWriter : Writer, ReadingWriter { void readSomething() { printf( "read2()" ); } } ================ There are no redundant interfaces in this example and yet ReadingWriter and WritingReader are not considered valid implementations. BUG NOTE!!! The above code crashes the compiler when I try to compile it so you may want to note this as a bug. (win32 version)
Jul 26 2004
You're talking about spelling mistakes here Sean. You can make exactly the same case for everyday methods also (no Interfaces anywhere to be seen):class A { void foo ( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E { void foo1 ( char x ) {} }class G : F { void ICantSpell() { super.foo ('!'); } } Oops! I mistyped super.foo() when I really meant super.foo1() ... what a silly billy <g> "Sean Kelly" <sean f4.ca> wrote in message news:ce3vq3$1ht7$1 digitaldaemon.com...In article <ce3rao$1g1s$1 digitaldaemon.com>, parabolis says...listWalter wrote:Why is simply omitting the redundant interface name in the inheritancedmdYou have a recursive inheritance declaration with ReadingWriter. Not thata problem? I don't get it.Initially I was inclined to side with you here and suggest you simply make it an error to include a redundant interface name and finally put the matter to rest. However it is not that simple. Consider: ================================ interface Reads { void readSomething(); } interface Writes { void writeSomething(); } interface ReadsWrites { void readSomething(); void writeSomething(); } class Reader : Reads { void readSomething() { printf( "read1()" ); } } class Writer : Writer{ void writeSomething() { printf( "write1()" ); } } class WritingReader : Reader, ReadingWriter { void writeSomething() { printf( "write2()" ); } } class ReadingWriter : Writer, ReadingWriter { void readSomething() { printf( "read2()" ); } } ================ There are no redundant interfaces in this example and yet ReadingWriter and WritingReader are not considered valid implementations. BUG NOTE!!! The above code crashes the compiler when I try to compile it so you may want to note this as a bug. (win32 version)should crash on it, but I suspect this is why :) Assuming you meant WritingReader for the second definition then you've still got a circular inheritance heirarchy which is not allowed. All that aside, should thisreallybe legal? interface I { void foo( char x ); } class A { void foo( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E, I { void foo( int x ) {} } Assume that all the above classes have very long definitions and that A,B, andC are in a third-party library with no documentation and convoluted, badly formatted import files. As the creator of F I may very well have intendedtodefine F.foo as the implementation for I.foo and just screwed up theprototype.With the existing lookup scheme this is flagged as an error but with the proposed scheme it would compile just fine. Further assume that A.foo isforsome completely different purpose as A may have no knowledge of interfaceI.IMO the proposed scheme will be the cause of some very hard to find bugs. Sean
Jul 26 2004
In article <ce414s$1icc$1 digitaldaemon.com>, Kris says...You're talking about spelling mistakes here Sean. You can make exactly the same case for everyday methods also (no Interfaces anywhere to be seen):hehe... It was an example, after all. I imagine a real case would be much more complex. What I was trying to point out was the risk of unintended consequences of the proposed lookup rules. The existing rules are explicit: the interface for each class is well-defined and if the user wants to leverage existing code then he can do so explicitly using alias. The result may be a bit more verbose but it's also far clearer IMO. I grant that the risk of mistakes isn't as great as if D supported multiple inheritance, but I think it's definately still there. And looking at my example, does it really seem reasonble that the code *should* compile? We're talking about a method that could be 10 levels up in the inheritance tree, and one which the implementer of F may not even know about. Perhaps I'm a control freak but I prefer my classes to have only the baggage I pack them with ;) Seanclass A { void foo ( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E { void foo1 ( char x ) {} }class G : F { void ICantSpell() { super.foo ('!'); } } Oops! I mistyped super.foo() when I really meant super.foo1() ... what a silly billy
Jul 26 2004
I would tend to agree with you regarding compilation Sean <g>. My view is that name overrides should not be treated as a special case. If you're going to be specific, then why not require the programmer to explicitly bring in each and every single method they wish to expose from the super-class? At least it would be symmetrical, and therefore consistent and easy to grok. However, although having to be explicit for *everything* would work beautifully regarding all these concerns, it might not meet with much agreement <g> My issue is that currently there's this half-way house approach: all non-private methods are inherited, except those that happen to have a name that happens to be used by the subclass. It's a special-case, and those are always prone to failure (I believe Vathix has one such failure scenario regarding alias and override). - Kris "Sean Kelly" <sean f4.ca> wrote in message news:ce41qm$1ij4$1 digitaldaemon.com...In article <ce414s$1icc$1 digitaldaemon.com>, Kris says...theYou're talking about spelling mistakes here Sean. You can make exactlymoresame case for everyday methods also (no Interfaces anywhere to be seen):hehe... It was an example, after all. I imagine a real case would be muchclass A { void foo ( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E { void foo1 ( char x ) {} }class G : F { void ICantSpell() { super.foo ('!'); } } Oops! I mistyped super.foo() when I really meant super.foo1() ... what a silly billycomplex. What I was trying to point out was the risk of unintendedconsequencesof the proposed lookup rules. The existing rules are explicit: theinterfacefor each class is well-defined and if the user wants to leverage existingcodethen he can do so explicitly using alias. The result may be a bit moreverbosebut it's also far clearer IMO. I grant that the risk of mistakes isn't asgreatas if D supported multiple inheritance, but I think it's definately stillthere.And looking at my example, does it really seem reasonble that the code*should*compile? We're talking about a method that could be 10 levels up in the inheritance tree, and one which the implementer of F may not even knowabout.Perhaps I'm a control freak but I prefer my classes to have only thebaggage Ipack them with ;) Sean
Jul 26 2004
Sean Kelly wrote:interface I { void foo( char x ); } class A { void foo( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E, I { void foo( int x ) {} } Assume that all the above classes have very long definitions and that A, B, and C are in a third-party library with no documentation and convoluted, badly formatted import files. As the creator of F I may very well have intended to define F.foo as the implementation for I.foo and just screwed up the prototype. With the existing lookup scheme this is flagged as an error but with the proposed scheme it would compile just fine. Further assume that A.foo is for some completely different purpose as A may have no knowledge of interface I. IMO the proposed scheme will be the cause of some very hard to find bugs.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. 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. 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. 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.
Jul 26 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
Jul 26 2004
"Sean Kelly" <sean f4.ca> wrote in message news:ce4gr1$1njs$1 digitaldaemon.com...In article <ce48ge$1klr$1 digitaldaemon.com>, parabolis says...much theWell, all that's needed is an alias, not a full stub, but that's prettysame thing. I like the stubs because they're explicit. Requiring their presence gives the programmer more control over how call resolution ishandled. 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.Ithink either way there will be the same number of ignorant programmersmakingapproximately the same number of stupid mistakes. Frankly, I'm on thefenceregarding this issue. In the presence of multiple inheritance I would befirmlyin the C++ camp, but without it I could probably be convinced that theproposedsolution is better. What I've been hoping for is that someone will comeup witha 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 errorsandwith maintaining a predictable and intuitive set of rules. I think theC++scheme provides that and I think the proposed scheme *may* provide that,but Iworry that I just haven't come up with a good enough reason why it doesnot. Did you see what Regan proposed? <g>
Jul 26 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
Jul 26 2004
Sean Kelly wrote:In article <ce4h8p$1nq7$1 digitaldaemon.com>, Kris says...Yes, I would think so, but that is because C++ don't have interfaces, only the possibility of classes that are abstract through having only method prototypes. These classes can be inherited to function as interfaces, but then other superclasses would be independent of the interface in the inheritance hierarchy. Lars Ivar IgesundMinor 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++?
Jul 27 2004
In article <ce4vka$1tvt$1 digitaldaemon.com>, Lars Ivar Igesund says...Sean Kelly wrote:Oops, of course. No wonder I had never run into it before. SeanIn article <ce4h8p$1nq7$1 digitaldaemon.com>, Kris says...Yes, I would think so, but that is because C++ don't have interfaces, only the possibility of classes that are abstract through having only method prototypes.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++?
Jul 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
Jul 26 2004
On Mon, 26 Jul 2004 22:15:32 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:All that aside, should this really be legal? interface I { void foo( char x ); } class A { void foo( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E, I { void foo( int x ) {} } Assume that all the above classes have very long definitions and that A, B, and C are in a third-party library with no documentation and convoluted, badly formatted import files. As the creator of F I may very well have intended to define F.foo as the implementation for I.foo and just screwed up the prototype. With the existing lookup scheme this is flagged as an error but with the proposed scheme it would compile just fine. Further assume that A.foo is for some completely different purpose as A may have no knowledge of interface I. IMO the proposed scheme will be the cause of some very hard to find bugs.I think a new keyword is required to show the programmers intent. i.e. "implement". If you are writing a method to satisfy an interface you preceed it with "implement" Using your example: class A { void foo( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E, I { implement void foo( int x ) {} } Would error saying "F.foo(int) does not implement any interface (I)" If the user then changed it to the correct definition: class F : E, I { implement void foo( char x ) {} } assuming override is mandatory, it would again error "F.foo(char) overrides A.foo(char)" so the user now needs: class F : E, I { implement override void foo( char x ) {} } This is _another_ argument _for_ a mandatory override keyword, _even if_ you don't agree a new implement keyword is a good idea. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 26 2004
"Regan Heath" <regan netwin.co.nz> wrote in message news:opsbrvovk35a2sq9 digitalmars.com...On Mon, 26 Jul 2004 22:15:32 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:Using your example: class A { void foo( char x ) {} } class B : A {} class C : B {} class D : C {} class E : D {} class F : E, I { implement void foo( int x ) {} } Would error saying "F.foo(int) does not implement any interface (I)" If the user then changed it to the correct definition: class F : E, I { implement void foo( char x ) {} } assuming override is mandatory, it would again error "F.foo(char) overrides A.foo(char)" so the user now needs: class F : E, I { implement override void foo( char x ) {} } This is _another_ argument _for_ a mandatory override keyword, _even if_ you don't agree a new implement keyword is a good idea.I think it's good example! Thanks Regan. I'm almost lost in this debates about override rules but I personally feel java rules are more intuitive for me (java experience). I've just now (reading debates) realized the actual mean of 'alias' and what does it for! And I think using alias in the inheritance is very NON-intuitive IMO but may be it's a habbit? What I do like in java are explicit keywords - 'extends' + 'implements'. What's all at this time. -------- Sorry for Off-topic: I'm not lawyer and don't know the rules. Actually they are can be different in different countries. It seems to me like this: For example, I'm single heir and I inherited some property from my parents by 'testament', 'will'. Testament says - I can use them all (inherited). 1. I have inherited all property 'by default' and can use it as I wish. 2. I can use them all because the are inherited by me. 3. But if I would like to give, bequeath it to my child I must write about usage of inheritance (EVERY property) 'explicitly' but NOT by default? Sound a little strang for me but it depends... Sorry again, just thoughts. ---- Yuriy.
Jul 26 2004
(Note this is a repost which corrects an example with a bug that crashes the compiler. Note the corrected version also crashes the compiler and thus I hope keeping the bug from be written off warrants reposting.) Walter wrote:Why is simply omitting the redundant interface name in the inheritance list a problem? I don't get it.Initially I was inclined to side with you here and suggest you simply make it an error to include a redundant interface name and finally put the matter to rest. However it is not that simple. Consider: ================================ interface Reads { void readSomething(); } interface Writes { void writeSomething(); } interface ReadsWrites { void readSomething(); void writeSomething(); } class Reader : Reads { void readSomething() { printf( "read1()" ); } } class Writer : Writer{ void writeSomething() { printf( "write1()" ); } } class WritingReader : Reader, Writes { void writeSomething() { printf( "write2()" ); } } class ReadingWriter : Writer, Reads { void readSomething() { printf( "read2()" ); } } ================================ There are no redundant interfaces in this example and yet ReadingWriter and WritingReader are not considered valid implementations. BUG NOTE!!! The above code crashes the compiler when I try to compile it so you may want to note this as a bug. (win32 version)
Jul 26 2004
You may have a typo here:class Writer : Writer{Should be "Writer : Writes" instead? That's probably what's choking the compiler. Other than that, then yes. You have to stub & dispatch for each of the inherited methods. It's no big deal with small interfaces, but quickly becomes messy (and brittle) once complexity ramps up to any significant degree. BTW, the redundant Interface thing was a complete red-herring :-) I made a mistake in my initial tardy example, and subsequently Walter thought that's what the issue was. My apologies. - Kris "parabolis" <parabolis softhome.net> wrote in message news:ce459o$1jnu$1 digitaldaemon.com...(Note this is a repost which corrects an example with a bug that crashes the compiler. Note the corrected version also crashes the compiler and thus I hope keeping the bug from be written off warrants reposting.) Walter wrote:listWhy is simply omitting the redundant interface name in the inheritancea problem? I don't get it.Initially I was inclined to side with you here and suggest you simply make it an error to include a redundant interface name and finally put the matter to rest. However it is not that simple. Consider: ================================ interface Reads { void readSomething(); } interface Writes { void writeSomething(); } interface ReadsWrites { void readSomething(); void writeSomething(); } class Reader : Reads { void readSomething() { printf( "read1()" ); } } class Writer : Writer{ void writeSomething() { printf( "write1()" ); } } class WritingReader : Reader, Writes { void writeSomething() { printf( "write2()" ); } } class ReadingWriter : Writer, Reads { void readSomething() { printf( "read2()" ); } } ================================ There are no redundant interfaces in this example and yet ReadingWriter and WritingReader are not considered valid implementations. BUG NOTE!!! The above code crashes the compiler when I try to compile it so you may want to note this as a bug. (win32 version)
Jul 26 2004
Kris wrote:You may have a typo here:Thanks. I was wrong, there is no bug.class Writer : Writer{Should be "Writer : Writes" instead? That's probably what's choking the
Jul 26 2004
Walter wrote:Sure. D originally worked the way you suggest. However, this message to meMy understanding of what Kris wants is both (1) inheritable interfaces _and_ (2) no function hiding for interface satisfaction Joe's message indicates that D originally satisfied (2) but not (1)-------------------------------------------- The fact that interfaces are snapshots and not inherited from class to subclass can really mess you up sometimes. Just tacking on the interface at eachCurrently (1) is satisfied but not (2). The reason Kris (rather indelicately) attacks the current implementation is both because the current implementation violates the inheritance aspect of the OO paradigm and because he does not see any valid justification for the violation. That the current implementation violates the inheritance aspect of the OO paradigm should be evident. Classes inherit except when satisfying interface requirements. Violating some aspect of the OO paradigm is not condemning in and of itself. As you pointed out in another post C++ also places restrictions on inheritance for the purpose of resolving against multiple possibilities. I doubt any non-trivial language can adhere perfectly to the OO paradigm. What is condemning is a violation without a reason. Your reason seems to be that 1) and 2) are not possible without a typehole. If you are right then there can be no similar language without the typehole. However Kris believes that Java is similar enough language to be a counter example. Since you have graciously made the relevant source public Kris also has the option to make the required changes to demonstrate the possibilty. I have an implementation in mind that might work. However I am still finding my way around the source and learning the basics behind OO implementation. Am I correct in assuming that dmd\src\phobos\internal\mars.h accurately portrays the memory layout? (ie a pointer to a Vtbl in memory points to a 32 bit value len which is followed by a 32 bit pointer to len 32 bit pointers) If so I am curious why an interface would need a Vtbl. Actually the fact that there is an Interface struct at all make me suspicious. ================================ (disclaimer - I have no idea how the following is actually done. Any pointers to more info would be appreciated.) ================================ I am assuming instantiated objects contain a pointer to their class's static data structure, which I am assuming is what ClassInfo represents. I am also assuming a Vtbl retains the super class' ordering of functions and extends the table by adding its new functions at the end and ovverides functions by replacing the pointers in the super class' Vtbl with appropriate pointers but otherwise copies the super class' Vtbl verbtatim. Finally I am assuming that ClassInfo's member baseClass is a pointer to the super class. Given these assumptions I would imagine interface data could be kept by assining a unique ID to each interface and keeping a table of all interfaces a class implements so that if class B is a subclass of class A then B's Interface table contains the union of the B's Interface IDs and A's IDs. For exampe if: A implements Interfaces with IDs 0, IDa, IDb and IDj, B implements Interfaces with IDs IDi, IDj, ... and IDk, then: A's table [0,IDa,IDb,IDj] B's table [0,IDa,IDb,IDi,IDj,...,IDk] A) Assigning an instantiated object, o, to an interface variable, i, would entail three steps at runtime: 1) verify that o has i's ID 2) create space for i 3) set i to point to the same thing o does B) The casting operation for an interface would require only one step at runtime: 1) verify that o has i's ID C) Assigning an instantiated object, o, to a class variable, c, would entail three steps at runtime: 1) verify that o can reach class c via baseclass 2) create space for i 3) set i to point to the same thing o does D) The casting operation for a class would also require only one step at runtime: 1) verify that o can reach class c via baseclass A), B), C) and D) above are the implict implementation. Explicit casting/assigning forgoes the implicit cast check. If function calls are made using a constant offset into the Vtbl in the ClassInfo that o has a pointer to then Joe Battelle's type-hole example is not a problem for this implementation. o's data is not changed by any of the operations used in Joe's code, so all the function calls are resolved with o's ClassInfo. Inherited functions can be allowed to satisfy an interface and interfaces are inherited. Since the ClassInfo interface table is a Set, redundant interfaces are trivial. Another benefit would seem to be that the ClassInfo Interfaces hold in the current implemntation would be eliminated.
Jul 26 2004
"parabolis" <parabolis softhome.net> wrote in message news:ce43mo$1j7c$1 digitaldaemon.com...What is condemning is a violation without a reason. Your reason seems to be that 1) and 2) are not possible without a typehole.Yes, that's exactly the reason I gave. It's not a violation without a reason.If you are right then there can be no similar language without the typehole. However Kris believes that Java is similar enough language to be a counter example.Maybe Java does indeed have a type hole in it.Am I correct in assuming that dmd\src\phobos\internal\mars.h accurately portrays the memory layout? (ie a pointer to a Vtbl in memory points to a 32 bit value len which is followed by a 32 bit pointer to len 32 bit pointers)The vtbls work just like in C++ single inheritance, except that the first entry is reserved for a reference to the .classinfo for the type.If so I am curious why an interface would need a Vtbl.For two reasons: 1) efficiency - polymorphic function dispatch via vtbl[] has proven to be very efficient. 2) compatibility with COM vtbl[]s.Actually the fact that there is an Interface struct at all make me suspicious.That's needed so that downcasting of interfaces can work.================================ (disclaimer - I have no idea how the following is actually done. Any pointers to more info would be appreciated.) ================================The best way to figure it out is to write a couple bits of sample code, compile them, and obj2asm the result. Also, check out phobos/internal/cast.d.
Jul 26 2004
You describe it as "The latter is utter nonsense, and smacks of either an implementation-specific hack or a half-baked and headless C-style implementation of method hiding." However, consider the following C++ program: -------------------------------------- C:\cbx>type foo.cpp #include <stdio.h> struct X { }; struct A { int foo(void *p) { return 1; } int foo(struct X x) { return 2; } }; struct B : A { // using A::foo; int foo(int i) { return 3; } }; void main() { B b; X x; int i; i = b.foo((void*)0); printf("i = %d\n", i); i = b.foo(x); printf("i = %d\n", i); i = b.foo(1); printf("i = %d\n", i); } C:\cbx>sc foo i = b.foo((void*)0); ^ foo.cpp(24) : Error: need explicit cast for function parameter 1 to get from: void * to : int i = b.foo(x); ^ foo.cpp(26) : Error: need explicit cast for function parameter 1 to get from: X to : int --- errorlevel 1 C:\cbx> ------------------------------------------- Now uncomment the 'using' declaration, and the program will compile successfully and produce the 1, 2, 3 output. Therefore, D uses overloading/hiding rules that are completely analogous to C++. I've read a lot of critiques of C++, and this has not been mentioned. Or perhaps my C++ compiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.
Jul 24 2004
In article <cdt9m6$puh$1 digitaldaemon.com>, Walter says...Therefore, D uses overloading/hiding rules that are completely analogous to C++. I've read a lot of critiques of C++, and this has not been mentioned. Or perhaps my C++ compiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.Agreed. The resolution rules might be complex but I think they make perfect sense once understood. And I personally find the consistency with C++ to be a good thing. Sean
Jul 24 2004
"Sean Kelly" <sean f4.ca> wrote in message news:cdu0jn$12bs$1 digitaldaemon.com...In article <cdt9m6$puh$1 digitaldaemon.com>, Walter says...aTherefore, D uses overloading/hiding rules that are completely analogous to C++. I've readC++lot of critiques of C++, and this has not been mentioned. Or perhaps myperfectcompiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.Agreed. The resolution rules might be complex but I think they makesense once understood. And I personally find the consistency with C++ tobe agood thing. SeanSean; would you mind explaining the benefits of those particular resolution rules to me please? While I may be both blind and stupid, I completely fail to see where the value lies, and no-one has specified what they are. Thanks;
Jul 24 2004
Kris wrote:"Sean Kelly" <sean f4.ca> wrote in message news:cdu0jn$12bs$1 digitaldaemon.com...As I wrote in http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/7011, I'm still not sure which side I'm on in this debate. I've often read people on this newsgroup lobbying for the compiler to *require* the programmer to do things the hard way to keep the programmer from accidentily doing things wrong. Before the alias is added, a person might remember that they meant to add ISomeInterface to the base class anyways. It's a hypothetical, but it's also a possible benefit. I am somewhat concerned that leaving out that alias can still silently fail to do what it's expected to do. For example, if I leave the alias out of the example below (based upon your example of course), in the MyWriter m.put(b) call, the bit b would be converted into a int. Oops. As I also mentioned in the other thread (http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/7011), the aliasing works if it's AFTER the new types. I don't know if it should be that way or has to be that way, but that's how it works in DMD 0.96. interface ISomeInterface{} class Writer { Writer put (bit x) { printf("Writer.put(bit x)\n"); return null; } Writer put (int x) { printf("Writer.put(int x)\n"); return null; } } class MyWriter : Writer { Writer put (int x) { printf("MyWriter.put(int x)\n"); return null; } Writer put (ISomeInterface x) { printf("Writer.put(ISomeInterface x)\n"); return null; } alias Writer.put put; } void main() { ISomeInterface I; int i; bit b; Writer w = new Writer(); MyWriter m = new MyWriter(); w.put(i); w.put(b); m.put(I); m.put(i); m.put(b); } Output: Writer.put(int x) Writer.put(bit x) Writer.put(ISomeInterface x) MyWriter.put(int x) Writer.put(bit x) -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/In article <cdt9m6$puh$1 digitaldaemon.com>, Walter says...aTherefore, D uses overloading/hiding rules that are completely analogous to C++. I've readC++lot of critiques of C++, and this has not been mentioned. Or perhaps myperfectcompiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.Agreed. The resolution rules might be complex but I think they makesense once understood. And I personally find the consistency with C++ tobe agood thing. SeanSean; would you mind explaining the benefits of those particular resolution rules to me please? While I may be both blind and stupid, I completely fail to see where the value lies, and no-one has specified what they are. Thanks;
Jul 24 2004
Hi Justin: inline "J C Calvarese"wrote ...I've often read people on this newsgroup lobbying for the compiler to *require* the programmer to do things the hard way to keep the programmer from accidentily doing things wrong. Before the alias isIf your referring to me, then yes; I do advocate such things. But in those where I do, it's when there's no other valid context (or, at least no-one has come up with anything to the contrary).added, a person might remember that they meant to add ISomeInterface to the base class anyways. It's a hypothetical, but it's also a possible benefit.The compiler would simply spit out an error saying it couldn't find a put(ISomeInterface), just as it does today within the scope of a self-contained class ~ the benefit of strongly-typed language. (BCPL would silently eat it).I am somewhat concerned that leaving out that alias can still silently fail to do what it's expected to do. For example, if I leave the alias out of the example below (based upon your example of course), in the MyWriter m.put(b) call, the bit b would be converted into a int. Oops.That's not what I'm suggesting at all Justin. From where I stand, all inherited signatures are still valid and the compiler picks the most appropriate one: Writer.put(bit) in your example. In other words, it should do /exactly/ what it would do today within the scope of a self-contained class. This latter part is key.As I also mentioned in the other thread (http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/7011), the aliasing works if it's AFTER the new types. I don't know if it should be that way or has to be that way, but that's how it works in DMD 0.96.This is surely indicative of another bug in method name resolution. The point I'm trying to make is this: there's a special case involved here, yet no-one can say /why/ it's a special case. My perspective is that it would be far simpler for both the programmer, and for the compiler, to treat inherited method signatures as though they were actually within the scope of the sub-class. By doing so, the compiler would treat inherited methods in exactly the same manner it treats them within a self-contained class, and there's no crufty edge conditions. Without a solid counter-point forthcoming, it's very hard for anyone to construct pros and cons ... There's another thing to consider: At the very least, I've pointed out no less than three non-obvious things, restricted entirely to the area of method name resolution. I think that spells trouble for anyone coming to the language. Don't you? As such I feel it's a very big mistake for Walter to simply "pooh pooh" the entire thing ... - Krisinterface ISomeInterface{} class Writer { Writer put (bit x) { printf("Writer.put(bit x)\n"); return null; } Writer put (int x) { printf("Writer.put(int x)\n"); return null; } } class MyWriter : Writer { Writer put (int x) { printf("MyWriter.put(int x)\n"); return null; } Writer put (ISomeInterface x) { printf("Writer.put(ISomeInterface x)\n"); return null; } alias Writer.put put; } void main() { ISomeInterface I; int i; bit b; Writer w = new Writer(); MyWriter m = new MyWriter(); w.put(i); w.put(b); m.put(I); m.put(i); m.put(b); } Output: Writer.put(int x) Writer.put(bit x) Writer.put(ISomeInterface x) MyWriter.put(int x) Writer.put(bit x) -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Jul 24 2004
Kris wrote:Hi Justin: inline "J C Calvarese"wrote ...You asked for an explanation of "the benefits of those particular resolution rules", so I came up a possible benefit. The benefit may be achieved better by another method but it could be a benefit. I suspect another benefit is that Walter thinks these rules are somewhat easy to implement, but I don't remember him mentioning anything specific to that effect.I've often read people on this newsgroup lobbying for the compiler to *require* the programmer to do things the hard way to keep the programmer from accidentily doing things wrong. Before the alias isIf your referring to me, then yes; I do advocate such things. But in those where I do, it's when there's no other valid context (or, at least no-one has come up with anything to the contrary).Lack of documentation is still a serious problem for D users. The spec only demonstrates how to do the simplest cases.added, a person might remember that they meant to add ISomeInterface to the base class anyways. It's a hypothetical, but it's also a possible benefit.The compiler would simply spit out an error saying it couldn't find a put(ISomeInterface), just as it does today within the scope of a self-contained class ~ the benefit of strongly-typed language. (BCPL would silently eat it).I am somewhat concerned that leaving out that alias can still silently fail to do what it's expected to do. For example, if I leave the alias out of the example below (based upon your example of course), in the MyWriter m.put(b) call, the bit b would be converted into a int. Oops.That's not what I'm suggesting at all Justin. From where I stand, all inherited signatures are still valid and the compiler picks the most appropriate one: Writer.put(bit) in your example. In other words, it should do /exactly/ what it would do today within the scope of a self-contained class. This latter part is key.As I also mentioned in the other thread (http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/7011), the aliasing works if it's AFTER the new types. I don't know if it should be that way or has to be that way, but that's how it works in DMD 0.96.This is surely indicative of another bug in method name resolution. The point I'm trying to make is this: there's a special case involved here, yet no-one can say /why/ it's a special case. My perspective is that it would be far simpler for both the programmer, and for the compiler, to treat inherited method signatures as though they were actually within the scope of the sub-class. By doing so, the compiler would treat inherited methods in exactly the same manner it treats them within a self-contained class, and there's no crufty edge conditions. Without a solid counter-point forthcoming, it's very hard for anyone to construct pros and cons ... There's another thing to consider: At the very least, I've pointed out no less than three non-obvious things, restricted entirely to the area of method name resolution. I think that spells trouble for anyone coming to the language. Don't you?As such I feel it's a very big mistake for Walter to simply "pooh pooh" the entire thing ...Often, Walter doesn't agree to change things until we gang up on him. I think there are really several issues at play here. Perhaps more could be achieved by breaking them into the separate parts: 1. External Names Possible solutions: a. Change the compiler to not do the offending behavior. b. Don't import within the class unless you want this behavior. If this still creates additional problems (as I know it did in the past with forward references), maybe those problems would be easier to fix that convincing Walter to redesign the name lookup rules. 2. Satisfying Interface Contracts I agree with you on this one. I don't understand at all why this doesn't automatically inherit the needed method. Am I being dense? Maybe we can convince Walter that this is an actual bug that needed fixing. 3. The Alias peek-a-boo Game Possible solutions: a. Change the compiler to not do the offending behavior. b. Clearly document that the alias should be added if the super's methods are wanted. Your document is well-organized, but it might be easier to build consensus one page at a time. Point 2 seems the least controversial, yet it also seems to be the least discussed in this thread.- Kris-- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Jul 24 2004
"J C Calvarese" <jcc7 cox.net> wrote in message news:cdurdu$1cm6$1 digitaldaemon.com...Kris wrote:thoseHi Justin: inline "J C Calvarese"wrote ...I've often read people on this newsgroup lobbying for the compiler to *require* the programmer to do things the hard way to keep the programmer from accidentily doing things wrong. Before the alias isIf your referring to me, then yes; I do advocate such things. But inno-onewhere I do, it's when there's no other valid context (or, at leastI'm sorry, there was a misunderstanding there. I was referring to a different topic where I've been advocating a stricter application of the language. I thought that's perhaps what you were referring to :-) You did indeed come up with possible benefits for this one, and those were much appreciated.has come up with anything to the contrary).You asked for an explanation of "the benefits of those particular resolution rules", so I came up a possible benefit. The benefit may be achieved better by another method but it could be a benefit.Often, Walter doesn't agree to change things until we gang up on him. I think there are really several issues at play here. Perhaps more could be achieved by breaking them into the separate parts: 1. External Names Possible solutions: a. Change the compiler to not do the offending behavior. b. Don't import within the class unless you want this behavior. If this still creates additional problems (as I know it did in the past with forward references), maybe those problems would be easier to fix that convincing Walter to redesign the name lookup rules. 2. Satisfying Interface Contracts I agree with you on this one. I don't understand at all why this doesn't automatically inherit the needed method. Am I being dense? Maybe we can convince Walter that this is an actual bug that needed fixing. 3. The Alias peek-a-boo Game Possible solutions: a. Change the compiler to not do the offending behavior. b. Clearly document that the alias should be added if the super's methods are wanted. Your document is well-organized, but it might be easier to build consensus one page at a time. Point 2 seems the least controversial, yet it also seems to be the least discussed in this thread.Breaking it into three topics is a good idea (I think it might have already happened). The reason they were all in one document to begin with is that there's perhaps an inherent problem with name resolution in general. All very good suggestions though. Please take a look at the revised document (posted soon) which speculates a reason for all of these "issues".- Kris-- Justin (a/k/a jcc7)
Jul 24 2004
"J C Calvarese" <jcc7 cox.net> wrote in message news:cduh40$18fr$1 digitaldaemon.com...As I also mentioned in the other thread (http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D/7011), the aliasing works if it's AFTER the new types. I don't know if it should be that way or has to be that way, but that's how it works in DMD 0.96.That's a compiler bug.
Jul 24 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu9ov$162i$1 digitaldaemon.com...Sean; would you mind explaining the benefits of those particularresolutionrules to me please? While I may be both blind and stupid, I completelyfailto see where the value lies, and no-one has specified what they are.Stroustrup has laid them out in chapter 13.1 of the "The Annotated C++ Reference Manual." The general rule for overloading is that a name is looked up first, and then overload resolution is applied. Stroustrup rejects the idea of ignoring scope issues when doing overload resolution. He argues that it would be surprising in a deeply nested heirarchy of class derivation, that a user of a derived class would have to know too much detail about a base class that may be hidden. Also, he shows how surprising errors can creep in, such as if a function in base class B copies only the B part of an object, but was inadvertantly called with an instance of D that didn't override each of those B functions properly.
Jul 24 2004
"Walter" <newshound digitalmars.com> wrote in message news:cdvhgv$1nf1$1 digitaldaemon.com..."Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu9ov$162i$1 digitaldaemon.com...lookedSean; would you mind explaining the benefits of those particularresolutionrules to me please? While I may be both blind and stupid, I completelyfailto see where the value lies, and no-one has specified what they are.Stroustrup has laid them out in chapter 13.1 of the "The Annotated C++ Reference Manual." The general rule for overloading is that a name isup first, and then overload resolution is applied. Stroustrup rejects the idea of ignoring scope issues when doing overload resolution. He arguesthatit would be surprising in a deeply nested heirarchy of class derivation, that a user of a derived class would have to know too much detail about a base class that may be hidden. Also, he shows how surprising errors can creep in, such as if a function in base class B copies only the B part ofanobject, but was inadvertantly called with an instance of D that didn't override each of those B functions properly.That is indeed the C++ view. However you forget a number of things: 1) D is better in so many ways than C++. It says so right there in the comparison charts ... <g> 2) C++ had to deal with multiple inheritance ~ I imagine that's a big factor in the above statement. D (and Java) do not. Notice how Java dispensed with the 'alias' notion completely, and did not pay this 'Stroustrup Tax' in any shape or form. 3) Aliasing method names is truly non-intuitive. It stands out like a sore thumb within D as a kludge. It does not matter from whence it came, or what supposed pedigree it has ~ so many other things in D are completely natural. 4) You may find that a required use of "override" would alleviate some of those Stroustrup concerns. 5) You are at least as smart as B.S., and can do much better than this. I can't help but be entirely suspicious about the B.S. Gospel applying in the same manner. I challenge you, Walter, to exceed C++ in this respect also. I further challenge you to provide a reasonable D example showing where this kind of alias thing is actually beneficial to the D programmer. If you cannot do that, then this Stroustrup argument holds no water whatsoever. Since we're all required to spend a bunch of time whittling down code in bug reports for you, I think it's only fair you do the same in return with respect to issues like this. I mean, if the value of alias is so obvious, how much effort would a few good examples really take? Regards; - Kris
Jul 24 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdvjvc$1osa$1 digitaldaemon.com..."Walter" <newshound digitalmars.com> wrote in message news:cdvhgv$1nf1$1 digitaldaemon.com...theStroustrup has laid them out in chapter 13.1 of the "The Annotated C++ Reference Manual." The general rule for overloading is that a name islookedup first, and then overload resolution is applied. Stroustrup rejectsaidea of ignoring scope issues when doing overload resolution. He arguesthatit would be surprising in a deeply nested heirarchy of class derivation, that a user of a derived class would have to know too much detail aboutofbase class that may be hidden. Also, he shows how surprising errors can creep in, such as if a function in base class B copies only the B partanStroustrup's arguments apply equally to D.object, but was inadvertantly called with an instance of D that didn't override each of those B functions properly.That is indeed the C++ view. However you forget a number of things: 1) D is better in so many ways than C++. It says so right there in the comparison charts ... <g>2) C++ had to deal with multiple inheritance ~ I imagine that's a bigfactorin the above statement. D (and Java) do not.This behavior of C++ predated MI by several years, and his argument is not about MI.Notice how Java dispensed with the 'alias' notion completely, and did notpay this 'Stroustrup Tax' in anyshape or form.I am not an experienced Java programmer, so I cannot give you an in-depth view of this from real world Java experience. But I do know that Java has made some serious errors in its language design, such as exception specifications (even though many Java programmers still believe it is a feature, not a bug <g>). So, I don't necessarilly believe that Java necessarilly got things right because Java is successful. On the other hand, I have a lot of real world experience with C++ and where programmers routinely crash & burn with it, and this behavior of C++ just doesn't come up as needing fixing.3) Aliasing method names is truly non-intuitive. It stands out like a sore thumb within D as a kludge. It does not matter from whence it came, orwhatsupposed pedigree it has ~ so many other things in D are completelynatural. That all depends on one's perspective. Aliasing symbols in D is the usual way to bring a name from one scope into another. It would seem counter-intuitive for this to not work with method names <g>.4) You may find that a required use of "override" would alleviate some of those Stroustrup concerns.I think that would require the base class designer to know about the derived classes, something that goes against OOP principles.5) You are at least as smart as B.S., and can do much better than this. I can't help but be entirely suspicious about the B.S. Gospel applying inthesame manner.Bjarne Stroustrup is a very smart man, and I've found his arguments are well founded in experience and rationality and not gospel. That doesn't mean I always agree with his conclusions, but one needs to have all one's ducks in a row if one wants to challenge his conclusions.I challenge you, Walter, to exceed C++ in this respect also.It's entirely possible that two reasonable people can look at the same data and draw different conclusions. In this case, which is better is a matter of opinion, and reasonable people can disagree. Using an alias declaration neatly produces the behavior you desire, but as another pointed out, if the Java rules were the default there doesn't seem to be nearly so simple a way to go the other way.I further challenge you to provide a reasonable D example showing wherethiskind of alias thing is actually beneficial to the D programmer. If you cannot do that, then this Stroustrup argument holds no water whatsoever. Since we're all required to spend a bunch of time whittling down code inbugreports for you, I think it's only fair you do the same in return with respect to issues like this. I mean, if the value of alias is so obvious, how much effort would a few good examples really take?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.
Jul 25 2004
Walter wrote: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 ? } -----------------------------------This creates a conflict and an explicit cast should be required.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.This is clearly bad design/programming of the class D. If you override some methods of B deliberately (as this person clearly do, he both use B.x and B.set), you damn sure need to know what's in B. Whether programmers doing this is able to make a good OO program at all, I highly doubt. (I don't imply that this example show your skill level in OOP, Walter :), but you should find a better example.) Lars Ivar Igesund
Jul 26 2004
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:ce2a40$f4t$1 digitaldaemon.com...This is clearly bad design/programming of the class D. If you override some methods of B deliberately (as this person clearly do, he both use B.x and B.set), you damn sure need to know what's in B.Of course - and that's the problem. It's an easy mistake to make, in my opinion, too easy.Whether programmers doing this is able to make a good OO program at all, I highly doubt. (I don't imply that this example show your skill level in OOP, Walter :), but you should find a better example.)It's obvious what's wrong when this is boiled down to such a tiny example. It isn't quite so obvious when it is married to all the usual cruft one finds in a class. Analogously, we both know that this C++ code: int *p; *p = 6; is bad code, and of course we wouldn't write that. But that kind of problem does crop up because it can be buried in a lot of other code. D has automatic initialization of variables to expose such problems. 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).
Jul 26 2004
On Mon, 26 Jul 2004 02:12:04 -0700, Walter <newshound digitalmars.com> wrote:"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:ce2a40$f4t$1 digitaldaemon.com...Aren't you only 'overloading/overriding' if the function signature is identical? 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/This is clearly bad design/programming of the class D. If you override some methods of B deliberately (as this person clearly do, he both use B.x and B.set), you damn sure need to know what's in B.Of course - and that's the problem. It's an easy mistake to make, in my opinion, too easy.Whether programmers doing this is able to make a good OO program at all, I highly doubt. (I don't imply that this example show your skill level in OOP, Walter :), but you should find a better example.)It's obvious what's wrong when this is boiled down to such a tiny example. It isn't quite so obvious when it is married to all the usual cruft one finds in a class. Analogously, we both know that this C++ code: int *p; *p = 6; is bad code, and of course we wouldn't write that. But that kind of problem does crop up because it can be buried in a lot of other code. D has automatic initialization of variables to expose such problems. 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).
Jul 26 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/
Jul 26 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...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.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.I know.-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/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/
Jul 26 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:resolution"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* overloadI think you mean "overriding" <g>.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.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 fromanotherscope, 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.-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/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/
Jul 26 2004
On Mon, 26 Jul 2004 23:02:07 -0700, Walter <newshound digitalmars.com> wrote:"Regan Heath" <regan netwin.co.nz> wrote in message news:opsbr73ixa5a2sq9 digitalmars.com...Either or, I used both above, you used both above in your original paragraph.On Mon, 26 Jul 2004 19:50:11 -0700, Walter <newshound digitalmars.com> wrote:resolution"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* overloadI think you mean "overriding" <g>.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,Common usage agrees with you, and perhaps my usage is a little loose, what I meant was that if you have a method foo(int) and you create foo(float) you're creating a method specifically to handle floats, thus it's a specialist method.. the looseness comes from the fact that the original method was also a specialist method to handle int, in fact that there is no generic method as it's impossible to write one, as we have no variant type.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.Perhaps.. what I am trying to say is that this: class X1 { void foo(int); } class X2 : X1 { void foo(float); } is _not_ the same as: class X1 { void foo(int); } class X2 : X1 { void foo(int); } the former 'extends' the parent class (I'll use extends instead of specialise), the latter overrides a method in the parent class. Ideally they should be treated differently. The former should be treated the same as if the methods had different names. This brings me to Issue 1: Requiring the use of 'override' facilitates treating them differently, if the programmer intends to override they say so, otherwise they assumed to be extending. This catches the accidental override and accidental not-override bugs. I believe it's a safe simple addition to the language. Issue 2: When you are extending a class you want it's public methods to be part of the child class, this works fine so long as the methods have different names, but, as soon as the methods have the same name you have to do something extra, i.e. use an alias, this is counter intuitive. I have no solution to this issue. Issue 3: When using interfaces, inherited methods do not satisfy the interface, this to me, is lunacy... why shouldn't they? The class does provide the methods the interface requires, it seems to me that to solve this all you need to do is walk the class heirarchy and notice the methods. Such that the following should be valid: interface FooBar { void foo(int a); void bar(int a); } class Parent { void foo(int a) { printf("Parent:foo:int\n"); } } class Child : Parent, FooBar { void bar(int a) { printf("Child:bar:int\n"); } } void main() { Child c = new Child(); c.foo(1); c.bar(2); } If Issue 2 and Issue 3 collide then it should be possible to use alias to alias-in the methods to satisfy the interface. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 27 2004
Regan Heath wrote:Aren't you only 'overloading/overriding' if the function signature is identical? Otherwise you're providing a specialisation i.e.I find it hard to follow your argumentation, probably due to the above statement. overloading and overriding is two different things: overriding is the reimplementation of a method in a subclass (having the same signature as a method in the superclass) overloading is when several methods/functions with the same name, but different signatures are provided. Lars Ivar Igesund
Jul 27 2004
In article <ce4st1$1sc2$1 digitaldaemon.com>, Lars Ivar Igesund says...overriding is the reimplementation of a method in a subclass (having the same signature as a method in the superclass) overloading is when several methods/functions with the same name, but different signatures are provided.So you can have a function which both overloads and overrides at the same time. And then there's "operator overloading" which means something else entirely, so now you can both overload and override an operator overload. Ah Jeez, I'm giving up on this one. Personally I think that "superclass" and "subclass" are named upside down*, so who am I to argue? Jill :) *If A is a superclass of B, then the set of member variables/methods of A is a SUBset of the set of member variables/methods of B.
Jul 27 2004
On Tue, 27 Jul 2004 08:36:45 +0100, Lars Ivar Igesund <larsivar igesund.net> wrote:Regan Heath wrote:I mean't overriding. I now have a better understanding of the common terminology, consider my paragraph to be... " Aren't you only overriding if the function signature is identical? Otherwise you're providing an overloading i.e. " Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/Aren't you only 'overloading/overriding' if the function signature is identical? Otherwise you're providing a specialisation i.e.I find it hard to follow your argumentation, probably due to the above statement. overloading and overriding is two different things: overriding is the reimplementation of a method in a subclass (having the same signature as a method in the superclass) overloading is when several methods/functions with the same name, but different signatures are provided.
Jul 27 2004
Thank you for the examples. "Walter" wrote .Stroustrup's arguments apply equally to D.But yet again you fail to qualify whyI am not an experienced Java programmer, so I cannot give you an in-depth view of this from real world Java experience. But I do know that Java has made some serious errors in its language design, such as exception specifications (even though many Java programmers still believe it is a feature, not a bug <g>). So, I don't necessarilly believe that Java necessarilly got things right because Java is successful. On the otherhand,I have a lot of real world experience with C++ and where programmers routinely crash & burn with it, and this behavior of C++ just doesn't come up as needing fixing.Nobody is saying that Java got everything right Walter. If it did, we wouldn't be here now, would we? I happen to agree with you that the Exception problem is very real, but let's not divert our focus yet again please. The point remains: if Java can handle it, then so can D. Rather than give that assertion some credence, you appear to brush it off as not even worth looking into.of4) You may find that a required use of "override" would alleviate somederivedthose Stroustrup concerns.I think that would require the base class designer to know about theclasses, something that goes against OOP principles.The D "override" keyword does not belong in a base class, as you well know. Instead, it goes into a derived class. I was referring to the debate over whether "override" should be mandatory or not, and perhaps that might help out with some of these concerns. Apparently it does not.opinion, and reasonable people can disagree. Using an alias declaration neatly produces the behavior you desire, but as another pointed out, iftheJava rules were the default there doesn't seem to be nearly so simple awayto go the other way.That's perhaps because you haven't given it very much thought? Do you perhaps think that not even one person on the NG could suggest a better approach? Or is that simply not an acceptable way to enhance the language? - Kris
Jul 26 2004
On Sun, 25 Jul 2004 23:18:41 -0700, Walter wrote:"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdvjvc$1osa$1 digitaldaemon.com...[snip]This example has now convinced me the both Stroustrup and Walter have got it wrong. At first, I thought that all I need do is make some explicit casts, but... Here is some D code to show it's madness... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} } class X3: X2 { void f(uint x) {printf("3\n");} } class X4: X3 { void f(char x) {printf("4\n");} } class X5: X4 { void f(double x){printf("5\n");} } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> And the result... c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 5 5 5 5 5 5 c:\temp> WHAT!?!? The coder has *explicitly* said he wanted an 'int'/'long'/'uint'... argument but D just went and converted to 'double' anyhow. Even the non-cast call did *not* use a double as the argument value; 1 is an integer not any form of floating point number. Then I changed X5 to include the 'alias X1.f f;' line and get this message... test.d(10): function f overloads void(double x) and void(int x) both match argument list for f WHAT?!?!? Since when is (double x) and (int x) the same? This is *not* a match. This current method matching rule is starting to seem more like lunacy than sanity. I thought compilers were supposed to help coders. This is just making more work rather than less work. Here is the code to make it work the 'intuitive' way... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} alias X1.f f; } class X3: X2 { void f(uint x) {printf("3\n");} alias X1.f f; alias X2.f f; } class X4: X3 { void f(char x) {printf("4\n");} alias X1.f f; alias X2.f f; alias X3.f f; } class X5: X4 { void f(double x){printf("5\n");} alias X1.f f; alias X2.f f; alias X3.f f; alias X4.f f; } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> <output> c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 1 2 3 4 5 1 </output> And that's just for *one* method.I further challenge you to provide a reasonable D example showing wherethiskind of alias thing is actually beneficial to the D programmer. If you cannot do that, then this Stroustrup argument holds no water whatsoever. Since we're all required to spend a bunch of time whittling down code inbugreports for you, I think it's only fair you do the same in return with respect to issues like this. I mean, if the value of alias is so obvious, how much effort would a few good examples really take?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.This type of bug is analogous to a spelling mistake. Its similar to the situation where two methods are spelled almost identically and the coder either chooses the wrong one or mistypes it. It is not a fault of OO or the language, but of the coder or class designer. I really don't mind being convinced that Walter (D) has got it right, but this argument doesn't do it. -- Derek Melbourne, Australia 26/Jul/04 4:45:21 PM
Jul 26 2004
Derek Parnell wrote:This example has now convinced me the both Stroustrup and Walter have got it wrong. At first, I thought that all I need do is make some explicit casts, but... Here is some D code to show it's madness... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} } class X3: X2 { void f(uint x) {printf("3\n");} } class X4: X3 { void f(char x) {printf("4\n");} } class X5: X4 { void f(double x){printf("5\n");} } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> And the result... c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 5 5 5 5 5 5 c:\temp> WHAT!?!? The coder has *explicitly* said he wanted an 'int'/'long'/'uint'... argument but D just went and converted to 'double' anyhow. Even the non-cast call did *not* use a double as the argument value; 1 is an integer not any form of floating point number.<snip>This current method matching rule is starting to seem more like lunacy than sanity. I thought compilers were supposed to help coders. This is just making more work rather than less work. Here is the code to make it work the 'intuitive' way...So, Walter, are you saying that alias is necessary to protect us from this? I, for one do not need to be protected from superclasses, and I think quite a few people are saying that. Why can't the scoping rules search EVERYWHERE for an exact match (since 99.999999% of the time that's what you intend), and then use your current scoping rules if you can't find an exact match? I agree with Derek: 'This current method matching rule is starting to seem more like lunacy than sanity'. Are you saying that I didn't know what I was doing as a programmer when I inherited from a base class, and I MUST use alias to show my intentions? This is one of the most counter-intuitive ideas I've seen in quite a while, and will send many budding library writers to an early D death, which is not what you are looking for. This is not anywhere near "The Principle of Least Surprise" Scott Sanders
Jul 26 2004
Derek Parnell wrote:Here is some D code to show it's madness... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} } class X3: X2 { void f(uint x) {printf("3\n");} } class X4: X3 { void f(char x) {printf("4\n");} } class X5: X4 { void f(double x){printf("5\n");} } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> And the result... c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 5 5 5 5 5 5 c:\temp> WHAT!?!? The coder has *explicitly* said he wanted an 'int'/'long'/'uint'... argument but D just went and converted to 'double' anyhow. Even the non-cast call did *not* use a double as the argument value; 1 is an integer not any form of floating point number.and inheritance have never been good bedfellows, if for no other reason than because the need for it rarely arises. That being said, extending a class is a conceptual joining of everything in the base class, plus everything defined in the subclass. It seems logical that the language reflect this behaviour and resolve names using the full class, not just the part of it defined in the current class block. This also inhibits things like template classes which generate class heirarchies from typelists, but this might be a good thing. ;) -- andy
Jul 26 2004
In article <ce3abq$1778$1 digitaldaemon.com>, Andy Friesen says...c:\temp>test 5 5 5 5 5 5 c:\temp>and inheritance have never been good bedfellows, if for no other reason than because the need for it rarely arises.I actually got caught out with this one a few years back - in C++. I thought the behavior was wrong then, and I still think it's wrong now. At the time, I didn't realize that C++ was defined that way, I just assumed that the compiler was crap. I had to workaround it by overriding the base class function in the derived class with an exact signature match, and defining the overridden function to call the base class function. That was a very time consuming bug to find, and the workaround/fix was not very satisfying. C++ got this one wrong. Java seems to have got it right. (In my humble opinion). This use of alias (in D) looks just like #define to me. That's obfuscation, not clarity. Jill
Jul 26 2004
"Arcane Jill" <Arcane_member pathlink.com> wrote in message news:ce3mb4$1dn3$1 digitaldaemon.com...I actually got caught out with this one a few years back - in C++. Ithought thebehavior was wrong then, and I still think it's wrong now. At the time, Ididn'trealize that C++ was defined that way, I just assumed that the compilerwascrap. I had to workaround it by overriding the base class function in the derived class with an exact signature match, and defining the overridden function to call the base class function. That was a very time consumingbug tofind, and the workaround/fix was not very satisfying. C++ got this onewrong.Java seems to have got it right. (In my humble opinion).Inserting a 'using' declaration in C++ is the usual way to make this work, not creating wrappers. The using declaration in that case works analogously to the 'alias' declaration in D.
Jul 26 2004
"Derek Parnell" <derek psych.ward> wrote in message news:ce2ce5$ib8$1 digitaldaemon.com...Here is some D code to show it's madness... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} } class X3: X2 { void f(uint x) {printf("3\n");} } class X4: X3 { void f(char x) {printf("4\n");} } class X5: X4 { void f(double x){printf("5\n");} } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> And the result... c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 5 5 5 5 5 5 c:\temp> 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.Even the non-cast call did *not* use a double as the argument value; 1 is an integer not any form of floating point number.But it's implicitly convertible to a double.Then I changed X5 to include the 'alias X1.f f;' line and get this message... test.d(10): function f overloads void(double x) and void(int x) both match argument list for f WHAT?!?!? Since when is (double x) and (int x) the same? This is *not* a match.That's a compiler bug :-(This current method matching rule is starting to seem more like lunacythansanity. I thought compilers were supposed to help coders. This is just making more work rather than less work. Here is the code to make it work the 'intuitive' way... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} alias X1.f f; } class X3: X2 { void f(uint x) {printf("3\n");} alias X1.f f; alias X2.f f; } class X4: X3 { void f(char x) {printf("4\n");} alias X1.f f; alias X2.f f; alias X3.f f; } class X5: X4 { void f(double x){printf("5\n");} alias X1.f f; alias X2.f f; alias X3.f f; alias X4.f f; } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> <output> c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 1 2 3 4 5 1 </output> And that's just for *one* method.It's not that bad. The following should work: class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} alias X1.f f; } class X3: X2 { void f(uint x) {printf("3\n");} alias X2.f f; } class X4: X3 { void f(char x) {printf("4\n");} alias X3.f f; } class X5: X4 { void f(double x){printf("5\n");} alias X4.f f; } 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.This type of bug is analogous to a spelling mistake. Its similar to the situation where two methods are spelled almost identically and the coder either chooses the wrong one or mistypes it.You're right. But spelling mistakes tend to get picked up by the compiler and show up as "undefined identifier" messages. Languages that implicitly declare misspelled identifiers tend to be very hard languages to debug code in. To extend the analogy to the example, I'd rather have to proactively say I want to include the declarations from another scope (with an alias declaration) than have it happen implicitly with no way to turn it off, and subtle problems result. Think of the alias declaration like an explicit cast - it tells the compiler (and the maintenance programmer) that "yes, I intended to do this" and the compiler says "yes sir, three bags full sir" and adds the methods into the scope and does the cast.
Jul 26 2004
In article <ce3c7j$18du$1 digitaldaemon.com>, Walter says..."Derek Parnell" <derek psych.ward> wrote in message news:ce2ce5$ib8$1 digitaldaemon.com...I like the current D scheme. In a sense, every class defines its own interface and calls are evaluated against this interface before walking the inheritance tree. This safety is a good thing. The alternative would be code that subtly breaks if a function prototype is added or altered somewhere up the inheritance tree. I'm surprised that folks can argue that "override" should be mandatory and then argue that the current D lookup scheme is broken, since the goal of both things is to protect the programmer from subtle inheritance-based coding errors. As far as the above example is concerned, perhaps this is an argument for the "explicit" keyword. It would certainly reduce or eliminate much of the confusion about D's lookup rules. SeanHere is some D code to show it's madness... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} } class X3: X2 { void f(uint x) {printf("3\n");} } class X4: X3 { void f(char x) {printf("4\n");} } class X5: X4 { void f(double x){printf("5\n");} } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> And the result... c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 5 5 5 5 5 5 c:\temp> 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.Even the non-cast call did *not* use a double as the argument value; 1 is an integer not any form of floating point number.But it's implicitly convertible to a double.
Jul 26 2004
On Mon, 26 Jul 2004 19:12:00 +0000 (UTC), Sean Kelly <sean f4.ca> wrote:In article <ce3c7j$18du$1 digitaldaemon.com>, Walter says...Requiring override protects you from doing this... class X1 { void read(ubyte[] buf); } classes X2 thru X8 class X9 : X8 { void read(ubyte[] buf); } In other words accidently overriding a function in a base class with the _exact same_ function signature. The problem with the lookup rules is _not_ that they do not find functions of the same signature, because they _do_, it's that they do not find functions of a different signature _without_ using alias. eg. class X1 { void read(char[] buf); } classes X2 thru X8 class X9 : X8 { void read(ubyte[] buf); } void main() { X9 p = new X9(); char[] line; p.read(line); }"Derek Parnell" <derek psych.ward> wrote in message news:ce2ce5$ib8$1 digitaldaemon.com...I like the current D scheme. In a sense, every class defines its own interface and calls are evaluated against this interface before walking the inheritance tree. This safety is a good thing. The alternative would be code that subtly breaks if a function prototype is added or altered somewhere up the inheritance tree. I'm surprised that folks can argue that "override" should be mandatory and then argue that the current D lookup scheme is broken, since the goal of both things is to protect the programmer from subtle inheritance-based coding errors.Here is some D code to show it's madness... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} } class X3: X2 { void f(uint x) {printf("3\n");} } class X4: X3 { void f(char x) {printf("4\n");} } class X5: X4 { void f(double x){printf("5\n");} } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> And the result... c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 5 5 5 5 5 5 c:\temp> 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.Even the non-cast call did *not* use a double as the argument value; 1 is an integer not any form of floating point number.But it's implicitly convertible to a double.As far as the above example is concerned, perhaps this is an argument for the "explicit" keyword. It would certainly reduce or eliminate much of the confusion about D's lookup rules. Sean-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Jul 26 2004
On Mon, 26 Jul 2004 02:59:49 -0700, Walter wrote:"Derek Parnell" <derek psych.ward> wrote in message news:ce2ce5$ib8$1 digitaldaemon.com......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. When I go to the beach and surf all day, its normal to get sand in my shorts, but it doesn't mean I like it.Here is some D code to show it's madness... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} } class X3: X2 { void f(uint x) {printf("3\n");} } class X4: X3 { void f(char x) {printf("4\n");} } class X5: X4 { void f(double x){printf("5\n");} } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> And the result... c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 5 5 5 5 5 5 c:\temp> 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.It's also implicitly convertible to many other things too! So why pick on 'double'?Even the non-cast call did *not* use a double as the argument value; 1 is an integer not any form of floating point number.But it's implicitly convertible to a double.Oh! Okay then.Then I changed X5 to include the 'alias X1.f f;' line and get this message... test.d(10): function f overloads void(double x) and void(int x) both match argument list for f WHAT?!?!? Since when is (double x) and (int x) the same? This is *not* a match.That's a compiler bug :-(Yep it does. That is a suitable reduction in typing.This current method matching rule is starting to seem more like lunacythansanity. I thought compilers were supposed to help coders. This is just making more work rather than less work. Here is the code to make it work the 'intuitive' way... <code> class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} alias X1.f f; } class X3: X2 { void f(uint x) {printf("3\n");} alias X1.f f; alias X2.f f; } class X4: X3 { void f(char x) {printf("4\n");} alias X1.f f; alias X2.f f; alias X3.f f; } class X5: X4 { void f(double x){printf("5\n");} alias X1.f f; alias X2.f f; alias X3.f f; alias X4.f f; } void main() { X5 p = new X5; p.f(cast(int)1); p.f(cast(long)1); p.f(cast(uint)1); p.f(cast(char)1); p.f(cast(double)1); p.f(1); } </code> <output> c:\temp>dmd test C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi; c:\temp>test 1 2 3 4 5 1 </output> And that's just for *one* method.It's not that bad. The following should work: class X1 { void f(int x) {printf("1\n");} } class X2: X1 { void f(long x) {printf("2\n");} alias X1.f f; } class X3: X2 { void f(uint x) {printf("3\n");} alias X2.f f; } class X4: X3 { void f(char x) {printf("4\n");} alias X3.f f; } class X5: X4 { void f(double x){printf("5\n");} alias X4.f f; }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."Agreed, but that's not what I was referring to. More like this ... void foo() { . . . }; void fooo() { . . . }; And the coder type in 'foo();' when they really meant 'fooo();' The compiler (and coder) aint <g> necessarily going to notice this until run time.This type of bug is analogous to a spelling mistake. Its similar to the situation where two methods are spelled almost identically and the coder either chooses the wrong one or mistypes it.You're right. But spelling mistakes tend to get picked up by the compiler and show up as "undefined identifier" messages. Languages that implicitly declare misspelled identifiers tend to be very hard languages to debug code in.To extend the analogy to the example, I'd rather have to proactively say I want to include the declarations from another scope (with an alias declaration) than have it happen implicitly with no way to turn it off, and subtle problems result. Think of the alias declaration like an explicit cast - it tells the compiler (and the maintenance programmer) that "yes, I intended to do this" and the compiler says "yes sir, three bags full sir" and adds the methods into the scope and does the cast.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 ;-) -- Derek Melbourne, Australia 27/Jul/04 11:05:01 AM
Jul 26 2004
"Derek Parnell" <derek psych.ward> wrote in message news:ce4bb2$1liq$1 digitaldaemon.com...'double'WHAT!?!? The coder has *explicitly* said he wanted an 'int'/'long'/'uint'... argument but D just went and converted toandanyhow.That's normal behavior, it's the integral argument promotion rules in CNo, 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.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.Because the only name in the scope takes a double as an argument.But it's implicitly convertible to a double.It's also implicitly convertible to many other things too! So why pick on 'double'?alongas the aliases become part of the names in a scope, and so get carriedgoodwith 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 afromthing because they show you *intended* to overload them based on namesYes.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."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 usethemethods 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 classYanduse 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>.
Jul 26 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]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 PMI 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>.
Jul 26 2004
In article <ce27vn$diq$1 digitaldaemon.com>, Walter says...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 ? } -----------------------------------X1.f, obviously. It's an exact match. There is no ambiguity there.His argument is that one can easilly miss an overload of f() somewhere in a complex class heirarchy,Then one should RTFM. Java, of course, has a compiler which can automatically generate documentation, which is a big boon. When you look at the docs for a Java class, you see an inheritance diagram, and can click on the superclass to see /its/ documentation. I believe Doxygen can do something like that for us in D, but not everyone uses it, and I'm not completely sure how it can connect a class to its superclass if they were written by different authors and exist in two completely independent modules. For example, everything derives from Object, but Object is not doxygenated. Java's Object class, by contrast, is fully Javadocked. It seems to me that this is actually an argument in favor of properly documenting everything in an integrated way. Another way to look at this is, this is perhaps a place where a lint-like-tool (OT: Why is it called "lint" anyway?) might issue a warning. But since D itself doesn't do warnings, it should just go ahead and compile it.and argues that one should not need to understand everything about a class heirarchy in order to derive from it.But why not? Okay, second example....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.<sarcasm>I take it you haven't heard of something called "design by contract" then? It's a feature of D which C++ does not possess.</sarcasm>
Jul 26 2004
But now you have turned a compile time bug into a run time bug I have to agree with walter here (I tend to undervalue DbC because so far it's been a runtime system, and I enjoy resting (more) easy once it compiles...) I'm never gonna test every branch in my whole code in a big enough project. however I still support this override keyword, and I have not heard Walter's comment on that :-)Okay, second example....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.<sarcasm>I take it you haven't heard of something called "design by contract" then? It's a feature of D which C++ does not possess.</sarcasm>
Jul 26 2004
"Arcane Jill" <Arcane_member pathlink.com> wrote in message news:ce2d32$iso$1 digitaldaemon.com...In article <ce27vn$diq$1 digitaldaemon.com>, Walter says...aStroustrup 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 ? } -----------------------------------X1.f, obviously. It's an exact match. There is no ambiguity there.His argument is that one can easilly miss an overload of f() somewhere inThe idea is to reduce the likelihood of unintentional behavior. It doesn't really do much good to keep telling people to RTFM.complex class heirarchy,Then one should RTFM.Because we are people and we don't work that way. How many of us even read the instructions that come with things? I can't remake people, all I can do is try to design a language that will reduce the probability of unintended consequences of not thoroughly understanding classes before making use of them. (Ever looked at STL classes? <g>) And I've myself made such mistakes even with base classes I wrote myself.and argues that one should not need to understand everything about a class heirarchy in order to derive from it.But why not?Okay, second example....contract"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.<sarcasm>I take it you haven't heard of something called "design bythen? It's a feature of D which C++ does not possess.</sarcasm>Of course, there's always the characteristic that if one boils a complex piece of code down to its minimum, the cause of the problem jumps out at one, and one could say don't write the code that way. When it happens in the real world, it happens buried in complex code with complicated interrelationships, it can be pretty hard to spot, and a simple DbC line may be inadequate. Furthermore, isn't it better to catch a bug without needing to write additional code to check for it?
Jul 26 2004
In article <ce27vn$diq$1 digitaldaemon.com>, Walter says...[...]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:I translated your example in Java, and it shows the "wrong" (non-C++) behaviour. The attached Test.java prints: The square is: 0 Ciao begin 0644 Test.java M('T-"B` ("!L;VYG('-Q=6%R94ET*"D >R!R971U<FX >"`J(' [('T-"GT- M" T*8VQA<W, 1"!E>'1E;F1S($(-"GL-"B` ("!L;VYG('-Q=6%R93L-"B` M("!V;VED('-E="AL;VYG(&DI('L <W5P97(N<V5T*&DI.R!S<75A<F4 /2!X M("H >#L ?0T*("` (&QO;F< <W%U87)E270H*2![(')E='5R;B!S<75A<F4[ M('T-"GT-" T*<'5B;&EC(&-L87-S(%1E<W0-"GL-"B` ("!S=&%T:6, ;&]N M1"!D(#T M("` 4WES=&5M+F]U="YP<FEN=&QN*")4:&4 <W%U87)E(&ES.B`B("L >"D[ ` end
Jul 26 2004
"Roberto Mariottini" <Roberto_member pathlink.com> wrote in message news:ce2gc7$kr2$1 digitaldaemon.com...In article <ce27vn$diq$1 digitaldaemon.com>, Walter says...aHis argument is that one can easilly miss an overload of f() somewhere inunderstandcomplex class heirarchy, and argues that one should not need totoeverything 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 needsbehaviour.alter a class state, and a derived class written later that 'caches' a computation on the derived state:I translated your example in Java, and it shows the "wrong" (non-C++)The attached Test.java prints: The square is: 0Thank-you. I expected Java to do that, it's nice to have confirmation.
Jul 26 2004
Once again, I find myself in the middle. Theoretically, I agree with you, Kris; the current rules don't make any sense. However, I think that I can use the same argument you used to support "override" to support Walter's position here. Here's the argument: You implement a class like this, where "Base" is a base class from some library: class Child : Base { void foo(int x) {...} } Then you write this code: extern (C) void call_foo(void *ptr, char c) { printf("I'm about to call foo(int)\n"); Child ref = cast(Child)ptr; assert(ref !== null); ref.foo(c); printf("I'm done calling foo(int)\n"); } This all works ok. Your code correctly does the implicit cast of char to int. However, later, the library adds a member function: class Base { void foo(char c) {...} } Base's foo() has nothing to do with your version of foo(). Should the code call Base.foo(char) or Child.foo(int)? Kris wrote:"Walter" <newshound digitalmars.com> wrote in message news:cdvhgv$1nf1$1 digitaldaemon.com..."Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu9ov$162i$1 digitaldaemon.com...lookedSean; would you mind explaining the benefits of those particularresolutionrules to me please? While I may be both blind and stupid, I completelyfailto see where the value lies, and no-one has specified what they are.Stroustrup has laid them out in chapter 13.1 of the "The Annotated C++ Reference Manual." The general rule for overloading is that a name isup first, and then overload resolution is applied. Stroustrup rejects the idea of ignoring scope issues when doing overload resolution. He arguesthatit would be surprising in a deeply nested heirarchy of class derivation, that a user of a derived class would have to know too much detail about a base class that may be hidden. Also, he shows how surprising errors can creep in, such as if a function in base class B copies only the B part ofanobject, but was inadvertantly called with an instance of D that didn't override each of those B functions properly.That is indeed the C++ view. However you forget a number of things: 1) D is better in so many ways than C++. It says so right there in the comparison charts ... <g> 2) C++ had to deal with multiple inheritance ~ I imagine that's a big factor in the above statement. D (and Java) do not. Notice how Java dispensed with the 'alias' notion completely, and did not pay this 'Stroustrup Tax' in any shape or form. 3) Aliasing method names is truly non-intuitive. It stands out like a sore thumb within D as a kludge. It does not matter from whence it came, or what supposed pedigree it has ~ so many other things in D are completely natural. 4) You may find that a required use of "override" would alleviate some of those Stroustrup concerns. 5) You are at least as smart as B.S., and can do much better than this. I can't help but be entirely suspicious about the B.S. Gospel applying in the same manner. I challenge you, Walter, to exceed C++ in this respect also. I further challenge you to provide a reasonable D example showing where this kind of alias thing is actually beneficial to the D programmer. If you cannot do that, then this Stroustrup argument holds no water whatsoever. Since we're all required to spend a bunch of time whittling down code in bug reports for you, I think it's only fair you do the same in return with respect to issues like this. I mean, if the value of alias is so obvious, how much effort would a few good examples really take? Regards; - Kris
Jul 26 2004
Walter wrote:"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu9ov$162i$1 digitaldaemon.com...Sorry, but that example has little to do with overloading, but very much to do with overriding. The B and D example shows: A superclass can have a method that cause problems for subclasses if it isn't overridden. Consequence: If this problematic situation should be solvable by the language, then a keyword meaning 'must be overridden' should be included. <code> mustoverride foo() {} </code> would mean that subclasses down through the hierarchy *must* override, in some cases doing only super.foo(); Another solution is to have override in the most super class of them all mean that they must be overridden in subclasses, while override in subclasses means what it do today. What the B and D example don't show: The public methods of a superclass should be hidden from a subclass' interface, if and only if the subclass have methods with the same name as those in the superclass, regardless of their signature. Consequence: Methods are hidden in some cases (those where overloading is involved), even though the normal case is that you don't want to hide. Using alias to unhide is weird. The word alias imply that the real name is hidden, but here it works the other way! The normal case is to want the superclass' methods up there in the subclass, but D has turned this upside down. Conclusion: Argumentation for why it should work the way it do today is lacking, and the implementation/specification is unintuitive, badly documented and works against most common use. All IMHO. Lars Ivar IgesundSean; would you mind explaining the benefits of those particularresolutionrules to me please? While I may be both blind and stupid, I completelyfailto see where the value lies, and no-one has specified what they are.Stroustrup has laid them out in chapter 13.1 of the "The Annotated C++ Reference Manual." The general rule for overloading is that a name is looked up first, and then overload resolution is applied. Stroustrup rejects the idea of ignoring scope issues when doing overload resolution. He argues that it would be surprising in a deeply nested heirarchy of class derivation, that a user of a derived class would have to know too much detail about a base class that may be hidden. Also, he shows how surprising errors can creep in, such as if a function in base class B copies only the B part of an object, but was inadvertantly called with an instance of D that didn't override each of those B functions properly.
Jul 25 2004
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:ce1ccn$2ru8$1 digitaldaemon.com...Argumentation for why it should work the way it do today is lacking, and the implementation/specification is unintuitive, badly documented and works against most common use. All IMHO.I can concur with "badly documented" <g> but why is the way C++ has worked for 20 years against most common use?
Jul 25 2004
I can concur with "badly documented" <g> but why is the way C++ has worked for 20 years against most common use?The fact that everyone got used to it doesn't mean it's the best. If people aren't conscious there are other options, they are not looking for them. Maybe that's the case going on here. D is trying to improve on C++, isn't it ? Ok, just give me a good example that either of the options is right, then make it work and I'll shut up.
Jul 25 2004
Lars made a series of valid points in his three emails Walter; as have many others. The fact that you choose to divert focus by ignoring his core points does not serve you well. You have been asked to clarify the /benefits/ of the current implementation several times now, in various ways, and still you avoid the issue at hand. One might be given pause to think you're avoiding this at all costs ... Please; I ask you once again: show us /all/ why this C++ style method-hiding is necessary and/or beneficial to D programmers via one or two examples. As I've already stated, if the benefits are so obvious then it won't take much effort on your part to do so. Posting that example of how C++ operates had absolutely zero value: we already /know/ it works that way ~ that's exactly the point of this issue ~ there's no perceived need for it to be that way in D at all! If you cannot show any benefits (for D) with some solid examples, then your position on this becomes seriously invalidated. Period. The whole point of this is to improve the D language; not to posture and swagger over academic excrement ... - Kris "Walter" <newshound digitalmars.com> wrote in message news:ce24ek$b1e$1 digitaldaemon.com..."Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:ce1ccn$2ru8$1 digitaldaemon.com...Argumentation for why it should work the way it do today is lacking, and the implementation/specification is unintuitive, badly documented and works against most common use. All IMHO.I can concur with "badly documented" <g> but why is the way C++ has worked for 20 years against most common use?
Jul 25 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in news:ce26ue$cm1$1 digitaldaemon.com:Lars made a series of valid points in his three emails Walter; as have many others. The fact that you choose to divert focus by ignoring his core points does not serve you well. You have been asked to clarify the /benefits/ of the current implementation several times now, in various ways, and still you avoid the issue at hand. One might be given pause to think you're avoiding this at all costs ...I don't get it. Why should the *benefits* be clarified, as long as the disadvantages remain unclear? Remember the old rule, if it's not broken, don't fix it.Please; I ask you once again: show us /all/ why this C++ style method-hiding is necessary and/or beneficial to D programmers via one or two examples. As I've already stated, if the benefits are so obvious then it won't take much effort on your part to do so.Consider that the benefits could be *hidden*, so there might be no easy way to that. But I think, that Walter, already did that quite well. Why should D take the look-up rules of a legacy language called Java?Posting that example of how C++ operates had absolutely zero value: we already /know/ it works that way ~ that's exactly the point of this issue ~ there's no perceived need for it to be that way in D at all!Disagree. It helped me better understand the D language and restrengthen my fading C++ skills. Futhermore some of those cool things you can do with C++ sprung back to my mind: class SomeClass : Base { alias Base.this this; // inherit *all* constructors } [I don't expect that this compiles with DMD, but the D language should allow it.] How do you do that the 'Java way'? Now some comments regarding your document (revision 4): Chapter External Names: Why is that chapter even still listed? Chapter Satisfying Interface Contracts: What's wrong with class Foo : IFoo { void foo() {} } class Bar : Foo, IBar { void bar() {} } And why do present the other solutions first, that are not really solutions, since why are *different* from the original example? <quote> Now your class design is explicitly bound by the design of the contract. In other words, the implementation is tightly bound to the layout of the contract. Given that the contract is supposed to be independent from the implementation, this is a truly sad place to be. <quote/> Why do you think that the *design* of the contract is of any importance? Generally, the *content* of the contract is of importance but not its design. I certainly could implement a class BarImpl2 in any way I could dream of, that fullfill's contract IBar and IFoo. Where's the catch, here? Chapter The Alias peek-a-boo Game: <quote> Here’s why: If one wishes to limit the exposure of class methods, one uses an Interface to represent only that portion of the concrete class that defines the external contract. <quote> And how do I get an interface of the hidden class instance? I would have to use factories, baggage, bloat, argh! <quote> Let’s recap some basic OO assumptions: a subclass is expected to inherit all methods from its super-class, unless declared private therein. The compiler is expected to provide override support where signatures match exactly. As such, the required use of alias for this fundamental behavior is non- intuitive, inappropriate, and defies commonly accepted OO practices. <quote> Personally, my OO assumption goes like this: A subclass must provide all the methods of its super-classes. As matter of *convenience* compilers implicitely take the method from the super-class to the subclass. (Except for some cases, e.g. constructors) But my point of view is rather non-intuitive, (mostly) inappropriate, and certainly does not belongs to commonly accepted OO practices. Farmer.
Jul 26 2004
<sigh> Inline Farmer: "Farmer" wrote...I don't get it. Why should the *benefits* be clarified, as long as the disadvantagesremainunclear? Remember the old rule, if it's not broken, don't fix it.You are welcome to your opinion, just as I am. However, you discredit the opinion of several others who have also stated their case regarding the disadvantages.Consider that the benefits could be *hidden*, so there might be no easywayto that. But I think, that Walter, already did that quite well. Why should D take the look-up rules of a legacy language called Java?it? I'm tempted to giggle ... but I won't.Disagree. It helped me better understand the D language and restrengthenmyfading C++ skills. Futhermore some of those cool things you can do withC++sprung back to my mind:Glad to hear it! My comments are all made in context Farmer: you're simply splitting hairs.class SomeClass : Base { alias Base.this this; // inherit *all* constructors } [I don't expect that this compiles with DMD, but the D language shouldallowit.] How do you do that the 'Java way'?Finally; this has some merit. Shame it's illegal syntax in D. What you fail to grasp, Farmer, is that I don't have a problem with alias as a concept at all. I've just documented a case where I feel it's required use is totally non-intuitive.Now some comments regarding your document (revision 4): Chapter External Names: Why is that chapter even still listed?Apparently, it must be for no reason other than to annoy you, Farmer. Don't you think it has some "educational" value? Just as example above had for you? Wouldn't you rather see the entire document simply disappear instead?Chapter Satisfying Interface Contracts: What's wrong with class Foo : IFoo { void foo() {} } class Bar : Foo, IBar { void bar() {} }It works great for small examples. You're simply repeating what I've already noted.And why do present the other solutions first, that are not reallysolutions,since why are *different* from the original example?Forgive me; my parser just failed.Why do you think that the *design* of the contract is of any importance? Generally, the *content* of the contract is of importance but not itsdesign.I certainly could implement a class BarImpl2 in any way I could dream of, that fullfill's contract IBar and IFoo. Where's the catch, here?You're absolutely right about the contract design. It should have no bearing whatsoever upon the class layout. This is exactly where the problem lies. As it is, If I construct a contract from several others, the class layout has to follow along in sych (as in the above example), unless you also provide a ream of stub & dispatch methods.Personally, my OO assumption goes like this: A subclass must provide allthemethods of its super-classes. As matter of *convenience* compilers implicitely take the method from the super-class to the subclass. (Exceptforsome cases, e.g. constructors) But my point of view is rather non-intuitive, (mostly) inappropriate, and certainly does not belongs to commonly accepted OO practices.Your just splitting hairs dude. I agree with your more pedantic version, but this has nothing to do with the issue. The fact is that the D compiler does not implicitly do what you state.
Jul 26 2004
Kris, I see I can follow your thoughts, and you can follow mine: We both agree that the overloading-rules are non-intuitive (I never admitted this before, but I do agree). We both agree that the 'alias hack' solves your problems, but it's non-intuitive, inconvenient, and against accepted OO-principles. We both agree, that the way, D currently supports interfaces, you *can* gain the basic (important) benefits of interfaces. although, it's non-intuitive, inconvenient, and limiting. What's different are not our *thoughts* (they are pretty much in line), but our conclusions. <em> You repeately argued that things are bullshit, since they are not intuitive. </em> Here my fundamental opinion is apparently different from yours. When I think of programming matters (language, libraries, methods), it is irrelevant whether sth. is intuitive or not. It is far more important, that things are consistent and logical. I prefer simple rules, that can be learnt and understood rather than intuitive rules or rules that are tweaked to archive intuitive results. I think that intuitive things are easy grasp, at first, but in the long run they are impossible to master. But the worst thing about intuitive designs are that they are context sensitive. What's intuitive depends on your background, on what you are currently working, and on personal preference. Since I have so strong feelings about the uselessness of intuitive design [Not long, when I read about Ruby that its designer made the language as intuitive as he could do. My intuition said 'Bullshit, don't bother to look at this.'], I fail to understand your paper, which appeals more to the reader's intuition than providing well presented trains of thoughts. I don't think its much of relevance, but my inituition share's you concerns that D's rules for implementation of interfaces, will/should be improved. I'm especialy concerned regarding templates (as Andy Friesen pointed out) and big messy class inheritance tries build by (even bigger an messier) programming teams. Regarding the 'alias peek a boo' game, I only comment that in the past, Walter had constantly sticked with 'C++' concepts, even when these concepts were undeniably more flawed, than the 'alias peek a boo' game. Farmer.I'm splitting hairs for good reasons: I consider your comment <quote> Posting that example of how C++ operates had absolutely zero value: we already /know/ it works that way ~ [...] </quote> as rude and unjustified: Not everyone has your skills and background to properly evaluate the 'alias- peek-a-boo game'. Walter is doing good in *repeatedly* explaining and clarifying the rules of D. (Especially if the description of these rules are so badly lacking in the specification ;-)Disagree. It helped me better understand the D language and restrengthenmyfading C++ skills. Futhermore some of those cool things you can do withC++sprung back to my mind:Glad to hear it! My comments are all made in context Farmer: you're simply splitting hairs.No, D needs critique papers to evolve and get rid of it's flaws. But why is there? (well, annoying me is for sure a good reason) Walter has already admitted that the presented problems are due to compiler- bugs. Would you also leave functions originally written to work-around some OS bugs, in code - or would you clean it up, once the issues were solved?Now some comments regarding your document (revision 4): Chapter External Names: Why is that chapter even still listed?Apparently, it must be for no reason other than to annoy you, Farmer. Don't you think it has some "educational" value? Just as example above had for you? Wouldn't you rather see the entire document simply disappear instead?I can fix that: And why do <you> present the other solutions first, that are not really solutions, since <they> are *different* from the original example? And to make sure it gets understood in the semantic phase ;-) Just one comment: Though, I'm used to see deliberate manipulations of the uninformed reader in sneaky marketing papers, I still consider it bad and inappropriate style.And why do present the other solutions first, that are not reallysolutions,since why are *different* from the original example?Forgive me; my parser just failed.
Jul 27 2004
Farmer wrote:Why should D take the look-up rules of a legacy language called Java?Heh, funny.
Jul 27 2004
In article <Xns95337DF59537itsFarmer 63.105.9.61>, Farmer says...Why should D take the look-up rules of a legacy language called Java?Not wishing to be /too/ pedantic, but C++ came before Java. So by that reckoning, C++ is "legacy" and Java is "modern". Jill
Jul 26 2004
Arcane Jill <Arcane_member pathlink.com> wrote in news:ce4ucm$1sqm$1 digitaldaemon.com:In article <Xns95337DF59537itsFarmer 63.105.9.61>, Farmer says...Ops, should read: Forget about the rules of the archaic C++ language and the legacy language Java. Better stick with modern languages: Smalltalk. :-) Farmer.Why should D take the look-up rules of a legacy language called Java? do it?Not wishing to be /too/ pedantic, but C++ came before Java. So by that reckoning, C++ is "legacy" and Java is "modern". Jill
Jul 27 2004
In article <cdt9m6$puh$1 digitaldaemon.com>, "Walter" <newshound digitalmars.com> wrote:You describe it as "The latter is utter nonsense, and smacks of either an implementation-specific hack or a half-baked and headless C-style implementation of method hiding." However, consider the following C++ program: -------------------------------------- C:\cbx>type foo.cpp #include <stdio.h> struct X { }; struct A { int foo(void *p) { return 1; } int foo(struct X x) { return 2; } }; struct B : A { // using A::foo; int foo(int i) { return 3; } }; void main() { B b; X x; int i; i = b.foo((void*)0); printf("i = %d\n", i); i = b.foo(x); printf("i = %d\n", i); i = b.foo(1); printf("i = %d\n", i); } C:\cbx>sc foo i = b.foo((void*)0); ^ foo.cpp(24) : Error: need explicit cast for function parameter 1 to get from: void * to : int i = b.foo(x); ^ foo.cpp(26) : Error: need explicit cast for function parameter 1 to get from: X to : int --- errorlevel 1 C:\cbx> ------------------------------------------- Now uncomment the 'using' declaration, and the program will compile successfully and produce the 1, 2, 3 output. Therefore, D uses overloading/hiding rules that are completely analogous to C++. I've read a lot of critiques of C++, and this has not been mentioned. Or perhaps my C++ compiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.I think his point has some validity to it. Importing should have a method by which to NOT implicitly be included in the current namespace as well as the module namespace. At least by my understanding of D imports he cannot do: std.c.linux.linux.close(...) without first importing. And by importing, he automatically gets close() in the current namespace. If there is already a way to "include" the module without "importing" the namespace then his point is moot. Otherwise I think there's something to this.
Jul 24 2004
In article <schancel-23ED78.09265224072004 digitalmars.com>, Sha Chancellor <schancel pacific.net> wrote:I think his point has some validity to it. Importing should have a method by which to NOT implicitly be included in the current namespace as well as the module namespace. At least by my understanding of D imports he cannot do: std.c.linux.linux.close(...) without first importing. And by importing, he automatically gets close() in the current namespace. If there is already a way to "include" the module without "importing" the namespace then his point is moot. Otherwise I think there's something to this.Pardon my stupidity, I meant to respond to external name resolution.
Jul 24 2004
Thanks Walter; Instead of falling back on tradition, why don't you look at it afresh? The salient point in this respect was as follows: "A subclass is expected to inherit all methods from its super-class, unless declared private therein. The compiler is expected to provide override support where signatures match exactly. As such, the required use of alias for this fundamental behavior is non-intuitive, inappropriate, and defies commonly accepted OO practices" You clearly don't agree with this, yet you don't question for a moment that the use of alias in this respect is, in fact, completely non-intuitive. Nor do you appear to think that perhaps there might be a better way to handle it. D can do a lot better than your example below. Just as Java can! This is clearly a special case scenario; I'm saying it shouldn't be. What on earth is the benefit? I implore you to please explain why it's so beneficial to hide these signatures, from the developers perspective? At least that would provide a solid counter-point. Regards; - Kris "Walter" <newshound digitalmars.com> wrote in message news:cdt9m6$puh$1 digitaldaemon.com...You describe it as "The latter is utter nonsense, and smacks of either an implementation-specific hack or a half-baked and headless C-style implementation of method hiding." However, consider the following C++ program: -------------------------------------- C:\cbx>type foo.cpp #include <stdio.h> struct X { }; struct A { int foo(void *p) { return 1; } int foo(struct X x) { return 2; } }; struct B : A { // using A::foo; int foo(int i) { return 3; } }; void main() { B b; X x; int i; i = b.foo((void*)0); printf("i = %d\n", i); i = b.foo(x); printf("i = %d\n", i); i = b.foo(1); printf("i = %d\n", i); } C:\cbx>sc foo i = b.foo((void*)0); ^ foo.cpp(24) : Error: need explicit cast for function parameter 1 to get from: void * to : int i = b.foo(x); ^ foo.cpp(26) : Error: need explicit cast for function parameter 1 to get from: X to : int --- errorlevel 1 C:\cbx> ------------------------------------------- Now uncomment the 'using' declaration, and the program will compile successfully and produce the 1, 2, 3 output. Therefore, D uses overloading/hiding rules that are completely analogous to C++. I've read a lot of critiques of C++, and this has not been mentioned. Or perhaps myC++compiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.
Jul 24 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu57d$1474$1 digitaldaemon.com...I implore you to please explain why it's so beneficial to hide these signatures, from the developers perspective? At least that would provide a solid counter-point.1) I find Stroustrup's argument in the ARM 13.1 (outlined in another message) reasonable. 2) In my experience with C++, this behavior has not caused an outcry and is not listed in any diatribes I've seen as one of the broken features of C++. 3) So I am reluctant to break with the C++ rule on this. The rule to apply is straightforward - look up the name, *then* apply overload resolution.
Jul 24 2004
On Sat, 24 Jul 2004 22:48:51 -0700, Walter wrote:"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu57d$1474$1 digitaldaemon.com...As brilliant as he is, could Stroustrup actually be wrong on the matter? Or to put it another way, D is not C++ so why do we have to follow Stroustrup's conventions within a language Stroustrup did not design?I implore you to please explain why it's so beneficial to hide these signatures, from the developers perspective? At least that would provide a solid counter-point.1) I find Stroustrup's argument in the ARM 13.1 (outlined in another message) reasonable.2) In my experience with C++, this behavior has not caused an outcry and is not listed in any diatribes I've seen as one of the broken features of C++.D is a different language, and this issue is now causing an outcry here that you deny exists elsewhere. The language seems to be different enough (perhaps because of so many features similar to Java) that this is indeed now an issue. The fact that D has different features from C++ makes a solution to these problems important to the language's future (even if they apparently weren't significant in C++). Also C++ has it's own community of personalities. The fact that complaints might be nonexistent in that community doesn't imply that the issue isn't important in the D community. What it comes down to is that it seems you have decided to follow C++ standards either for convenience or preference. I guess that's good to know.3) So I am reluctant to break with the C++ rule on this. The rule to apply is straightforward - look up the name, *then* apply overload resolution.This appears to be a Java verses C++ debate. Does java define name lookup rules differently (someone indicated so in another message, I believe)? If so, why is the C++ way better then the java way? The C++ model shouldn't always be the right one to imitate, should it? As it stands, I think your adoption of C++ name lookup rules into the D language has made it confusing. Is that what happens when you mix C++ and Java ancestry? I don't fully comprehend the nitty gritty details of this, but it makes for interesting debate! I just hope there's a useful resolution to it all. Later, John
Jul 24 2004
"John Reimer" <brk_6502 yahoo.com> wrote in message news:pan.2004.07.25.06.30.45.581020 yahoo.com...Heaven knows I disagree with Dr. Stroustrup on many points. However, this is a case where I agree with him. I am not simply doing it that way because Dr. Stroustrup did it that way.1) I find Stroustrup's argument in the ARM 13.1 (outlined in another message) reasonable.As brilliant as he is, could Stroustrup actually be wrong on the matter? Or to put it another way, D is not C++ so why do we have to follow Stroustrup's conventions within a language Stroustrup did not design?of2) In my experience with C++, this behavior has not caused an outcry and is not listed in any diatribes I've seen as one of the broken featuresI followed this aspect of C++ because I found the argument in favor of it compelling, and since D is a refactoring of C++ and not Java, it gives greater weight to C++ behavior over Java behavior.C++.D is a different language, and this issue is now causing an outcry here that you deny exists elsewhere. The language seems to be different enough (perhaps because of so many features similar to Java) that this is indeed now an issue. The fact that D has different features from C++ makes a solution to these problems important to the language's future (even if they apparently weren't significant in C++). Also C++ has it's own community of personalities. The fact that complaints might be nonexistent in that community doesn't imply that the issue isn't important in the D community. What it comes down to is that it seems you have decided to follow C++ standards either for convenience or preference. I guess that's good to know.Java explicitly differs from C++ in this regard. Kris is arguing for Java lookup/overriding rules. I see no reason that Java should be always be the right one to imitate, either <g>.The rule to apply is straightforward - look up the name, *then* apply overload resolution.This appears to be a Java verses C++ debate. Does java define name lookup rules differently (someone indicated so in another message, I believe)? If so, why is the C++ way better then the java way? The C++ model shouldn't always be the right one to imitate, should it?
Jul 25 2004
"Walter" wrote ...Java explicitly differs from C++ in this regard. Kris is arguing for Java lookup/overriding rules. I see no reason that Java should be always be the right one to imitate, either <g>.I am, huh? I thought I was advocating logical progression and continuity of behavior. This is /not/ something the D compiler currently has with respect to name resolution. Far from it actually ... what about imitating ease-of-use and common sense, Walter? <g> I really think you need to show us some good code examples of why this is so much to our benefit, and not a maligned detraction instead.
Jul 25 2004
In article <cdvrf1$1unf$1 digitaldaemon.com>, Kris says..."Walter" wrote ...This discussion would probably be better continued once the associated compiler bugs have been fixed. Without the ability to offer practical working examples of how the existing scheme does not work, I think there's the potential for a bit of confusion over specifics. SeanJava explicitly differs from C++ in this regard. Kris is arguing for Java lookup/overriding rules. I see no reason that Java should be always be the right one to imitate, either <g>.I am, huh? I thought I was advocating logical progression and continuity of behavior. This is /not/ something the D compiler currently has with respect to name resolution. Far from it actually ... what about imitating ease-of-use and common sense, Walter? <g>
Jul 25 2004
That would be a fair point Sean, but the issue is not about the bugs surrounding alias; it's about the necessity of its arcane and non-intuitive use. My document deliberately avoided pointing out the bugs still there, to avoid exactly this kind of confusion. It doesn't change the basic premise ... <g> I'm still waiting for Walter (or anyone) to provide a good code example or two that shows exactly why D needs this. Without that, the vague argument about what B.S. believes holds no water whatsoever with respect to D -- in other words, there is /still/ no solid counter-point to examine. It's in all our interests to get this resolved properly ~ so bring on the examples I say! :-) "Sean Kelly" <sean f4.ca> wrote in message news:ce0s5l$2gne$1 digitaldaemon.com...In article <cdvrf1$1unf$1 digitaldaemon.com>, Kris says...Java"Walter" wrote ...Java explicitly differs from C++ in this regard. Kris is arguing forthelookup/overriding rules. I see no reason that Java should be always beofright one to imitate, either <g>.I am, huh? I thought I was advocating logical progression and continuityrespectbehavior. This is /not/ something the D compiler currently has withcompilerto name resolution. Far from it actually ... what about imitating ease-of-use and common sense, Walter? <g>This discussion would probably be better continued once the associatedbugs have been fixed. Without the ability to offer practical workingexamplesof how the existing scheme does not work, I think there's the potentialfor abit of confusion over specifics. Sean
Jul 25 2004
Walter wrote:I followed this aspect of C++ because I found the argument in favor of it compelling, and since D is a refactoring of C++ and not Java, it gives greater weight to C++ behavior over Java behavior.---Java explicitly differs from C++ in this regard. Kris is arguing for Java lookup/overriding rules. I see no reason that Java should be always be the right one to imitate, either <g>.IMHO, C++ is *not* the language you want to imitate when it comes to OOP issues. Java and Eiffel are better suited; Java because the single inheritance/interface model is used by D, Eiffel because it seems to work even if everything is possible. Lars Ivar Igesund
Jul 25 2004
On Sun, 25 Jul 2004 00:06:49 -0700, Walter <newshound digitalmars.com> wrote:"John Reimer" <brk_6502 yahoo.com> wrote in message news:pan.2004.07.25.06.30.45.581020 yahoo.com...You should choose the one that best suits D. It appears you believe you have done that. It appears Kris disagrees. So, I am on the fence until I have seen: - a good outline of both the C++ and Java name resolution methods. - some D code examples where one or the other is better/easier/more intuitive. I personally find having to use 'alias' counter intuitive. My background is one in C (the last 6 years of my life), not C++ or Java. I have used Java a tiny bit, and C++ perhaps 10x more than that. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/Heaven knows I disagree with Dr. Stroustrup on many points. However, this is a case where I agree with him. I am not simply doing it that way because Dr. Stroustrup did it that way.1) I find Stroustrup's argument in the ARM 13.1 (outlined in another message) reasonable.As brilliant as he is, could Stroustrup actually be wrong on the matter? Or to put it another way, D is not C++ so why do we have to follow Stroustrup's conventions within a language Stroustrup did not design?of2) In my experience with C++, this behavior has not caused an outcryandis not listed in any diatribes I've seen as one of the broken featuresI followed this aspect of C++ because I found the argument in favor of it compelling, and since D is a refactoring of C++ and not Java, it gives greater weight to C++ behavior over Java behavior.C++.D is a different language, and this issue is now causing an outcry here that you deny exists elsewhere. The language seems to be different enough (perhaps because of so many features similar to Java) that this is indeed now an issue. The fact that D has different features from C++ makes a solution to these problems important to the language's future (even if they apparently weren't significant in C++). Also C++ has it's own community of personalities. The fact that complaints might be nonexistent in that community doesn't imply that the issue isn't important in the D community. What it comes down to is that it seems you have decided to follow C++ standards either for convenience or preference. I guess that's good to know.Java explicitly differs from C++ in this regard. Kris is arguing for Java lookup/overriding rules. I see no reason that Java should be always be the right one to imitate, either <g>.The rule to apply is straightforward - look up the name, *then* apply overload resolution.This appears to be a Java verses C++ debate. Does java define name lookup rules differently (someone indicated so in another message, I believe)? If so, why is the C++ way better then the java way? The C++ model shouldn't always be the right one to imitate, should it?
Jul 25 2004
In article <pan.2004.07.25.06.30.45.581020 yahoo.com>, John Reimer <brk_6502 yahoo.com> wrote:On Sat, 24 Jul 2004 22:48:51 -0700, Walter wrote:If the alias thing is a bug, I disagree on all counts. I like the option of not including the overloaded members which I didn't overload. There may be cases where a child class does not want those to be inherited. Which is allowed by the current method. If it becomes the default behavior to inherit them, you'd need to have some kind of convention to get RID of them."Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu57d$1474$1 digitaldaemon.com...As brilliant as he is, could Stroustrup actually be wrong on the matter? Or to put it another way, D is not C++ so why do we have to follow Stroustrup's conventions within a language Stroustrup did not design?I implore you to please explain why it's so beneficial to hide these signatures, from the developers perspective? At least that would provide a solid counter-point.1) I find Stroustrup's argument in the ARM 13.1 (outlined in another message) reasonable.2) In my experience with C++, this behavior has not caused an outcry and is not listed in any diatribes I've seen as one of the broken features of C++.D is a different language, and this issue is now causing an outcry here that you deny exists elsewhere. The language seems to be different enough (perhaps because of so many features similar to Java) that this is indeed now an issue. The fact that D has different features from C++ makes a solution to these problems important to the language's future (even if they apparently weren't significant in C++). Also C++ has it's own community of personalities. The fact that complaints might be nonexistent in that community doesn't imply that the issue isn't important in the D community. What it comes down to is that it seems you have decided to follow C++ standards either for convenience or preference. I guess that's good to know.3) So I am reluctant to break with the C++ rule on this. The rule to apply is straightforward - look up the name, *then* apply overload resolution.This appears to be a Java verses C++ debate. Does java define name lookup rules differently (someone indicated so in another message, I believe)? If so, why is the C++ way better then the java way? The C++ model shouldn't always be the right one to imitate, should it? As it stands, I think your adoption of C++ name lookup rules into the D language has made it confusing. Is that what happens when you mix C++ and Java ancestry? I don't fully comprehend the nitty gritty details of this, but it makes for interesting debate! I just hope there's a useful resolution to it all. Later, John
Jul 25 2004
"Sha Chancellor" <schancel pacific.net> wrote in message news:schancel-512344.09114325072004 digitalmars.com...If the alias thing is a bug, I disagree on all counts. I like the option of not including the overloaded members which I didn't overload. There may be cases where a child class does not want those to be inherited. Which is allowed by the current method. If it becomes the default behavior to inherit them, you'd need to have some kind of convention to get RID of them.That is another way to look at it. It can be a problem if one has an arbitrarilly deep inheritance heirarchy, and there's an overlooked (!) overload in there. The alias can also be used to 'opt-in' only the functions from a particular subclass in the inheritance heirarchy, not all of them. The 'alias' idiom for doing an 'opt-in' can be thought of another way - by creating an alias for a symbol in the current scope, doesn't it make sense that it then enables overloading between the scopes on that name? Note that this is the same behavior when one creates an alias for other function names, even names in other imports, etc. It's a powerful thing, but it shouldn't be on by default.
Jul 25 2004
Walter wrote:"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu57d$1474$1 digitaldaemon.com...The rule would still be straightforward if it was: look up the name, apply overload resolution if overload resolution fails; repeat above for superclass Lars Ivar IgesundI implore you to please explain why it's so beneficial to hide these signatures, from the developers perspective? At least that would provide a solid counter-point.1) I find Stroustrup's argument in the ARM 13.1 (outlined in another message) reasonable. 2) In my experience with C++, this behavior has not caused an outcry and is not listed in any diatribes I've seen as one of the broken features of C++. 3) So I am reluctant to break with the C++ rule on this. The rule to apply is straightforward - look up the name, *then* apply overload resolution.
Jul 25 2004
"Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:ce1bpg$2rjr$2 digitaldaemon.com...Walter wrote:That's a good thought, but overload resolution is not pass/fail, it has multiple levels of matching. You'll have to decide if a worse match in the current scope is better or worse than a better match in another scope. It'll be an arbitrary rule, one more bit of arcana needed to program in D.The rule to apply is straightforward - look up the name, *then* apply overload resolution.The rule would still be straightforward if it was: look up the name, apply overload resolution if overload resolution fails; repeat above for superclass
Jul 25 2004
What you specifically avoid in your reply, Walter, is that an EXACT (yes, that is a shout) match may be in the very next scope. Additionally, the rules involved are no different that those applied for the current scope; there's simply more signatures to choose from. You really appear to be deliberately obfuscating the issue ... why? - Kris "Walter" <newshound digitalmars.com> wrote in message news:ce2676$c4d$1 digitaldaemon.com..."Lars Ivar Igesund" <larsivar igesund.net> wrote in message news:ce1bpg$2rjr$2 digitaldaemon.com...It'llWalter wrote:That's a good thought, but overload resolution is not pass/fail, it has multiple levels of matching. You'll have to decide if a worse match in the current scope is better or worse than a better match in another scope.The rule to apply is straightforward - look up the name, *then* apply overload resolution.The rule would still be straightforward if it was: look up the name, apply overload resolution if overload resolution fails; repeat above for superclassbe an arbitrary rule, one more bit of arcana needed to program in D.
Jul 25 2004
Walter wrote:The rule to apply is straightforward - look up the name, *then* apply overload resolution.I have read what /feels/ like thousands of posts in which you repeated that phrase. I am reluctant to add even another drop to this river but sadly it looks like I will be contributing. In the context of resolving names within a nested scope the rule is simple and straightforward: 1) Attempt overload resolution in the most specific scope first and if that fails then try the next more general scope... rinse... repeat. How could it be simpler? You have said elsewhere that you are concerned making exceptions to this rule will result in an arcane language with arcane rules. That is a valid fear. The very people asking for an exception are motivated by exactly the same fear. However they want to see this rule applied: 2) A subclass inherits everything from its base class. (emphasis on the period.) Surely you can understand that the following seems arcane: 2) A subclass inherits everything from its base class, 2a) except for the purpose of satisfying an interface and 2b) except when overload resolution is satisfied by something in the subclass 2bi) unless that something is 'alias'ed to bring a base class' name into scope. Now consider the suggested amended 1): 1) Attempt overload resolution in the most specific scope first and if that fails then try the next more general scope... rinse... repeat 1a) except when finding inherited functions which should first be attempted without overload resolution. It seems obvious to me that either the scope resolution rules or the inheritance rules are going to get more complicated. Unless someone else can find a less complicated way to amend 2) I do not believe it is wise to make inheritance overly complicated to keep scope resolution simple. Of course this tendency is also influenced by the fact that I believe inheritance is more important than scope rules simply because it has more intuitive oomph which is really what makes the OO paradigm so useful. It feels like the scope rules are more helpful to people from a C++ background than the general population who can inuit OO's inheritance rather easily. That is why I believe you have had to explain the simple scope rules over and over in the thread...
Jul 28 2004
parabolis wrote:It feels like the scope rules are more helpful to people from a C++ background than the general population who can inuit OO's inheritance rather easily. That is why I believe you have had to explain the simple scope rules over and over in the thread...They are. But as I pointed out in another post, D is different from C++ in that D method functions are virtual by default. For this reason I think your argument is worth considering. In C++ ther rules make sense because all default behavior is static. In D the rules make less sense because most default behavior is dynamic. The presence of interfaces and the lack of multiple inheritance just strengthens the argument in my mind. Though I think it is important to note that the override issue that Regan has mentioned should be considered separately from this one. Sean
Jul 27 2004
Sean Kelly wrote:parabolis wrote:That is good to hear. I am by no means an avid C++ programmer mostly because I have not internalized what other C++ programmers have internalized and so I am rather cautious about advocating a suggestion for D that would be violently counter-intuitive to C++ programmers.It feels like the scope rules are more helpful to people from a C++ background than the general population who can inuit OO's inheritance rather easily. That is why I believe you have had to explain the simple scope rules over and over in the thread...They are. But as I pointed out in another post, D is different from C++ in that D method functions are virtual by default. For this reason I think your argument is worth considering. In C++ ther rules make sense because all default behavior is static. In D the rules make less sense because most default behavior is dynamic. The presence of interfaces and the lack of multiple inheritance just strengthens the argument in mymind. Though I think it is important to note that the override issue that Regan has mentioned should be considered separately from this one.Yes the two are seperate and it was probably bad form to include the interface issue in a post that deals mostly with the seperate issue of overriding. (The post was actually about overriding and not interfaces) However I felt I had to include the interface issue to illustrate the ways in which D is already tending towards arcane as far exceptions to the inheritance go.
Jul 28 2004
Also, please note that following doesn't even compile: class Writer { void put (bit x){} void put (int x){} } class MyWriter : Writer { alias Writer.put put; void put (bit x){} } "function put conflicts with MyWriter.put"
Jul 24 2004
In article <cdu5f0$14dm$1 digitaldaemon.com>, Kris says...Also, please note that following doesn't even compile: class Writer { void put (bit x){} void put (int x){} } class MyWriter : Writer { alias Writer.put put; void put (bit x){} } "function put conflicts with MyWriter.put"I'd forgotten about this detail. And adding override doesn't help. Okay so I do have a gripe or two with C++ name resolution rules ;) Sean
Jul 24 2004
Kris wrote:Also, please note that following doesn't even compile: class Writer { void put (bit x){} void put (int x){} } class MyWriter : Writer { alias Writer.put put; void put (bit x){} } "function put conflicts with MyWriter.put"I'm not saying you're wrong on the broader issues (I'm still trying to understand the various viewpoints), but this problem seems to be solvable by moving the alias to the *end*. Don't ask me to explain it or justify it (I can't), but maybe this specific case is more of a compiler bug. I think Walter's a lot more flexible about fixing compiler bugs that rewriting his carefully designed lookup rules. Here's my short (yet complete) code: class MyWriter : Writer { void put (bit x) { printf("MyWriter.put(bit x)\n"); } alias Writer.put put; } void main() { bit b; int i; Writer w = new Writer(); MyWriter m = new MyWriter(); w.put(b); w.put(i); m.put(b); m.put(i); } -- Justin (a/k/a jcc7) http://jcc_7.tripod.com/d/
Jul 24 2004
On Sat, 24 Jul 2004 10:17:01 -0700, Kris wrote:Also, please note that following doesn't even compile: class Writer { void put (bit x){} void put (int x){} } class MyWriter : Writer { alias Writer.put put; void put (bit x){} } "function put conflicts with MyWriter.put"This is just a bug. If the sub-class has a method with the same signature as the *first* method in the super class and the alias appears before the methods, then the alias will generate an error message. Try swapping the methods in the Writer class. Message goes away. Change the signature in the sub-class to (int x). Message goes away. Move the alias to be after the method in the sub-class. Message goes away. This is just a bug. -- Derek Melbourne, Australia
Jul 24 2004
I don't think anyone suggested that particular one was anything else, Derek. It's broken. Full Stop. With luck it'll get fixed. If you are feeling some animosity towards me, then please email directly outlining your issue. And thanks for not shouting this time! - Kris "Derek" <derek psyc.ward> wrote in message news:i546196c2uti$.1stk2dxkftgx4.dlg 40tude.net...On Sat, 24 Jul 2004 10:17:01 -0700, Kris wrote:Also, please note that following doesn't even compile: class Writer { void put (bit x){} void put (int x){} } class MyWriter : Writer { alias Writer.put put; void put (bit x){} } "function put conflicts with MyWriter.put"This is just a bug. If the sub-class has a method with the same signature as the *first* method in the super class and the alias appears before the methods, then the alias will generate an error message. Try swapping the methods in the Writer class. Message goes away. Change the signature in the sub-class to (int x). Message goes away. Move the alias to be after the method in the sub-class. Message goes away. This is just a bug. -- Derek Melbourne, Australia
Jul 24 2004
On Sat, 24 Jul 2004 17:47:19 -0700, Kris wrote:I don't think anyone suggested that particular one was anything else, Derek. It's broken. Full Stop. With luck it'll get fixed.Sorry, it seemed to me that you were implying that this current behaviour is designed that way.If you are feeling some animosity towards me, then please email directly outlining your issue. And thanks for not shouting this time!What????? "animosity" ... "shouting" ... I don't get it. Why do you think that I'm angry or being nasty. Sorry if I come across that way, but it isn't (isnt/aint/isnot) so. -- Derek Melbourne, Australia
Jul 24 2004
And that is a compiler bug! "Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu5f0$14dm$1 digitaldaemon.com...Also, please note that following doesn't even compile: class Writer { void put (bit x){} void put (int x){} } class MyWriter : Writer { alias Writer.put put; void put (bit x){} } "function put conflicts with MyWriter.put"
Jul 24 2004
Walter wrote:You describe it as "The latter is utter nonsense, and smacks of either an implementation-specific hack or a half-baked and headless C-style implementation of method hiding." However, consider the following C++ program: --------------------------------------...------------------------------------------- Now uncomment the 'using' declaration, and the program will compile successfully and produce the 1, 2, 3 output. Therefore, D uses overloading/hiding rules that are completely analogous to C++. I've read a lot of critiques of C++, and this has not been mentioned. Or perhaps my C++ compiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.I believe this example is misleading. The name resolution is important in C++ only because struct B might inherit from a second struct, say Y, which also implements 'int foo(int i)'. C++ cannot (and would not) be critiqued because it must resolve against multiple super classes. Using C++ rules designed to select from a multiple inheritance hierarchy in D does not make sense. I do not believe it is possible to justify hiding anything in a single inheritance language.
Jul 25 2004
"parabolis" <parabolis softhome.net> wrote in message news:ce12bi$2l2r$1 digitaldaemon.com...Walter wrote:anYou describe it as "The latter is utter nonsense, and smacks of eitheraimplementation-specific hack or a half-baked and headless C-style implementation of method hiding." However, consider the following C++ program: --------------------------------------...------------------------------------------- Now uncomment the 'using' declaration, and the program will compile successfully and produce the 1, 2, 3 output. Therefore, D uses overloading/hiding rules that are completely analogous to C++. I've readC++lot of critiques of C++, and this has not been mentioned. Or perhaps myC++ had this behavior from the beginning, long before it had multiple inheritance. (Although the 'using' declaration came years after MI was implemented.)compiler has an egregious fault in it, but I find it hard to believe it would have lasted this long with such a fundamental flaw <g>.I believe this example is misleading. The name resolution is important in C++ only because struct B might inherit from a second struct, say Y, which also implements 'int foo(int i)'. C++ cannot (and would not) be critiqued because it must resolve against multiple super classes. Using C++ rules designed to select from a multiple inheritance hierarchy in D does not make sense. I do not believe it is possible to justify hiding anything in a single inheritance language.
Jul 25 2004
"some idiot" <fu bar.org> wrote in message news:cdsd5t$u5$1 digitaldaemon.com...Attached is a small pdf noting three outstanding issues ~ each of whichhasvarious bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.External Names: I can't seem to recreate that problem, but I have some thoughts on it. I think importing in a class is like importing in a module. If there is a symbol collision, you have to specify from which scope you want the symbol. What comes to mind is this, which does not work: FileConduit fc = new FileConduit; fc.FileConduit.read("foo"); Although, I think if you don't have access (it's private, etc) to something it should not cause a collision. I've been meaning to make a post on that. A working solution is to wrap your imports in a struct or something, and instead of std.linux.linux.read(), simply use mystruct.read(). Satisfying Interface Contracts: From class.html#interface it says "A reimplemented interface must implement all the interface functions, it does not inherit them from a super class." I don't see why you're specifying to (re)implement IFoo without reimplementing it. You can't specify a base class twice, why are you doing it for an interface? It just so happens that specifying to implement an interface has an added feature for reimplementing. In fact, when I tried it with a class, the compiler crashed! The Alias peek-a-boo Game: I remember reading that it helps prevent the possibility of accidentally calling the wrong function. Actually, I think there was a big long thread on it, and I think people said they'd rather opt-into this danger using an alias. However, there is a problem when trying to both override and alias overload; I've been meaning to bug post it (wow I'm lazy ;).
Jul 24 2004
"Vathix" wroteSatisfying Interface Contracts: From class.html#interface it says "A reimplemented interface mustimplementall the interface functions, it does not inherit them from a super class."Idon't see why you're specifying to (re)implement IFoo withoutreimplementingit. You can't specify a base class twice, why are you doing it for an interface? It just so happens that specifying to implement an interfacehasan added feature for reimplementing. In fact, when I tried it with aclass,the compiler crashed!Sorry ... there was a typo in the example. Fixed in the revision.The Alias peek-a-boo Game: I remember reading that it helps prevent the possibility of accidentally calling the wrong function. Actually, I think there was a big long threadonit, and I think people said they'd rather opt-into this danger using an alias. However, there is a problem when trying to both override and alias overload; I've been meaning to bug post it (wow I'm lazy ;).This is just the kind of sneaky issue that manifests once the compiler starts to special-case certain conditions. My position is that the compiler should treat inherited methods in effectively the same manner as if they were all declared within the subclass itself (sans override for the moment). It's simpler for the compiler and simpler for the user. If this were the case, you would not have the problem you ran into <g>
Jul 24 2004
"Vathix" <vathixSpamFix dprogramming.com> wrote in message news:cdta9c$q1c$1 digitaldaemon.com...Satisfying Interface Contracts: From class.html#interface it says "A reimplemented interface mustimplementall the interface functions, it does not inherit them from a super class."Idon't see why you're specifying to (re)implement IFoo withoutreimplementingit. You can't specify a base class twice, why are you doing it for an interface? It just so happens that specifying to implement an interfacehasan added feature for reimplementing. In fact, when I tried it with aclass,the compiler crashed!I hope you send me the example that caused a crash!
Jul 24 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
Jul 26 2004
Let me explain what is happening here. In FileConduit, you have an import declaration, which brings a bunch of names into FileConduit's scope. 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. The solution is straightforward. Move the import declaration outside of the class. Then it won't override base class names. There's no need whatsoever to refactor class heirarchies. By where you place the import declaration, you specify when the lookups for the names in the import happen.
Jul 24 2004
"Walter" <newshound digitalmars.com> wrote in message news:cdtapd$q5m$1 digitaldaemon.com...Let me explain what is happening here. In FileConduit, you have an import declaration, which brings a bunch of names into FileConduit's scope. How name lookup happens in a scope is a multi-stage process, each proceeding to the next if the name is not foundinthe 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 overrideimportsin the current scope, i.e. if imports were looked up in some other scope than the one in which they were imported. The solution is straightforward. Move the import declaration outside oftheclass. Then it won't override base class names. There's no need whatsoever to refactor class heirarchies. By where you place the import declaration, you specify when the lookups for the names in the import happen.That's wonderful! However, you avoided a significant attribute of the issue in that signature matching is abandoned during the matching process. That is, there is no notion of looking to see if there's a better 'signature' match. As I stated; the import of those two linux function names blows away the other signatures. This seems like a half-way house, but I can certainly /imagine/ why your compiler might choose not to do that. Perhaps the most serious problem is that said issue does not manifest within FileConduit itself. It's only when a call is placed (from some other module) to either read() or close() that the compile breaks. I thought John Reimer stated it rather well in his post (7/24/2004,12:41) on the subject. Lastly: You, and many others, are acutely aware of the problems related to forward references. Placing the import inside the class scope is currently the /only/ way to resolve some of those. Now we have to move imports outside the class-scope just so we can call certain methods therein. Do you see the conflict here? What I personally find strange, Walter, is that such conflicts just don't seem to register as valid problems. At least now we know what the compiler does.
Jul 24 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu94m$15t6$1 digitaldaemon.com...That's wonderful! However, you avoided a significant attribute of theissuein that signature matching is abandoned during the matching process. That is, there is no notion of looking to see if there's a better 'signature' match. As I stated; the import of those two linux function names blowsawaythe other signatures. This seems like a half-way house, but I cancertainly/imagine/ why your compiler might choose not to do that.It's following the rule that name lookup happens first, *then* overload resolution. Signatures only have relevance to overload resolution, and no relevance to name lookup. I worry that if I start breaking this rule for special cases here and there, the resulting confusion would be far, far worse, and would relegate D to an "experts only" language. I think we're served better by simple, universally applied rules even if we're not happy with the result in some odd cases.Perhaps the most serious problem is that said issue does not manifestwithinFileConduit itself. It's only when a call is placed (from some othermodule)to either read() or close() that the compile breaks. I thought John Reimer stated it rather well in his post (7/24/2004,12:41) on the subject.By importing a bunch of names into a scope, well, those names get found in that scope. Put the import outside of that scope!Lastly: You, and many others, are acutely aware of the problems related to forward references. Placing the import inside the class scope is currently the /only/ way to resolve some of those. Now we have to move importsoutsidethe class-scope just so we can call certain methods therein. Do you seetheconflict here?The later DMD versions do a better job of handling forward references. If I have specific examples of where that still fails, I can work on that. Putting the imports in the class scope is, I believe, the wrong solution, and even worse would be trying to hammer it to fit.What I personally find strange, Walter, is that such conflicts just don't seem to register as valid problems. At least now we know what the compiler does.What I interpret is going on here is that imports inside classes are attempts at working around a forward reference problem. The solution is to get at the forward reference problem.
Jul 24 2004
The later DMD versions do a better job of handling forward references. If I have specific examples of where that still fails, I can work on that. Putting the imports in the class scope is, I believe, the wrong solution, and even worse would be trying to hammer it to fit.I'm satisfied with this solution. As long as forward reference issues can be settled, I'll have no problem putting imports external to classes (that's where I figure they should be anyway). But fixing those forward reference errors will be a long, difficult road anyway because the complicated problems typically don't melt down to the simple examples you so admire. I still don't like the way an import can override the way it does, but it obviously becomes a non-issue at this point if the necessity of the internal import is taken away.What I personally find strange, Walter, is that such conflicts just don't seem to register as valid problems. At least now we know what the compiler does.What I interpret is going on here is that imports inside classes are attempts at working around a forward reference problem. The solution is to get at the forward reference problem.
Jul 24 2004
If you can't fix imports to act as though outer-scope methods have somehow been "aliased into scope", then I humbly suggest you make it illegal to allow an import within the class scope. I do that all the time for one good reason: all version(linux) and version(Win32) stuff should be isolated together wherever possible. This means I deliberately place imports inside class boundaries, because it is the most maintainable way to set things up (you don't have to go grubbing around trying to find/edit some reference elsewhere). If you make inner imports illegal, then you'll ultimately make the code less maintainable. But even I would grudgingly admit that's better than the obnoxious behavior currently exposed. Of course, one or the other really has to be remedied: forward references or, uhhhh, smarter name resolution ... current versions of DMD do not cut it for the former or the latter. - Kris "Walter" <newshound digitalmars.com> wrote in message news:cdvimn$1o5c$1 digitaldaemon.com..."Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu94m$15t6$1 digitaldaemon.com...ThatThat's wonderful! However, you avoided a significant attribute of theissuein that signature matching is abandoned during the matching process.Reimeris, there is no notion of looking to see if there's a better 'signature' match. As I stated; the import of those two linux function names blowsawaythe other signatures. This seems like a half-way house, but I cancertainly/imagine/ why your compiler might choose not to do that.It's following the rule that name lookup happens first, *then* overload resolution. Signatures only have relevance to overload resolution, and no relevance to name lookup. I worry that if I start breaking this rule for special cases here and there, the resulting confusion would be far, far worse, and would relegate D to an "experts only" language. I think we're served better by simple, universally applied rules even if we're not happy with the result in some odd cases.Perhaps the most serious problem is that said issue does not manifestwithinFileConduit itself. It's only when a call is placed (from some othermodule)to either read() or close() that the compile breaks. I thought Johntostated it rather well in his post (7/24/2004,12:41) on the subject.By importing a bunch of names into a scope, well, those names get found in that scope. Put the import outside of that scope!Lastly: You, and many others, are acutely aware of the problems relatedcurrentlyforward references. Placing the import inside the class scope isIthe /only/ way to resolve some of those. Now we have to move importsoutsidethe class-scope just so we can call certain methods therein. Do you seetheconflict here?The later DMD versions do a better job of handling forward references. Ifhave specific examples of where that still fails, I can work on that. Putting the imports in the class scope is, I believe, the wrong solution, and even worse would be trying to hammer it to fit.don'tWhat I personally find strange, Walter, is that such conflicts justcompilerseem to register as valid problems. At least now we know what thedoes.What I interpret is going on here is that imports inside classes are attempts at working around a forward reference problem. The solution is to get at the forward reference problem.
Jul 25 2004
"Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdvrns$1uqn$1 digitaldaemon.com...If you can't fix imports to act as though outer-scope methods have somehow been "aliased into scope", then I humbly suggest you make it illegal to allow an import within the class scope. I do that all the time for one good reason: all version(linux) and version(Win32) stuff should be isolated together wherever possible. This means I deliberately place imports inside class boundaries, because it is the most maintainable way to set things up (you don't have to go grubbing around trying to find/edit some reference elsewhere). If you make inner imports illegal, then you'll ultimately make the code less maintainable.Buteven I would grudgingly admit that's better than the obnoxious behavior currently exposed. Of course, one or the other really has to be remedied: forward references or, uhhhh, smarter name resolution ... current versions of DMD do not cut it for the former or the latter.C'mon, Kris! You import the names into a scope, and then want the names to not be found. I don't think that is a resolvable problem. I admit to the documentation being inadequate, but after I explained the 4 simple steps of name lookup rules and when in the process overload resolution applies, the behavior you've seen is straightforward. C++ has loads of magic special rules that apply in arcane situations, and nobody understands them, they just dink around with the source until it appears to work. I'll be happy to work on any forward referencing issues.
Jul 25 2004
"Walter" wrote ..C'mon, Kris! You import the names into a scope, and then want the names to not be found. I don't think that is a resolvable problem. I admit to the documentation being inadequate, but after I explained the 4 simple stepsofname lookup rules and when in the process overload resolution applies, the behavior you've seen is straightforward. C++ has loads of magic special rules that apply in arcane situations, and nobody understands them, they just dink around with the source until it appears to work. I'll be happy to work on any forward referencing issues.Once again, Walter; you appear to be deliberately ignoring the core issue. I most certainly did not state anything of the sort, regarding your opening salvo. I absolutely do want the names to be found: all signatures! That's the problem here! And again, this is not C++. How many people have to say that to you? It's not good enough to just DINK AROUND until it works, as you say. Unless this is just a bit of a laugh for you? If it is, then I'll stop wasting my time with your little game and move on. Try to look at this from an objective standpoint please? 1) Some external names were imported. Period. 2) They happened to conflict with some existing class method names. Period. 3) Instead of overloading, the imports hid the internal names completely from the outside world. No errors. Period. 4) In this case, when switching from Win32 to Linux, a bunch of class methods mysteriously disappeared from view. Period. 5) Hours of debugging time was spent tracking down thoroughly misleading compiler error messages. Period. This maketh a problem Walter. Not a personal opinion. Yes, you explained the four steps and they simply point out the serious limitations of the C++ model as applied to D. Indeed, you can simply cover up said limitations by not allowing imports within a class scope. Fair enough. I simply pointed out why I was taking advantage of the inner import, with respect to "locality of reference" vis-a-vis maintainability. For doing so, I proffer my deepest apologies. - Kris
Jul 25 2004
The later DMD versions do a better job of handling forward references. If I have specific examples of where that still fails, I can work on that. Putting the imports in the class scope is, I believe, the wrong solution, and even worse would be trying to hammer it to fit.Very true, I tried compiling DFL with .94 ( or some such ) and it died with tons of forward refrences, while .96 worked without a hitch. I Think that old FR workaround should be abandoned ( thank goodness ). Charlie In article <cdvimn$1o5c$1 digitaldaemon.com>, Walter says..."Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cdu94m$15t6$1 digitaldaemon.com...That's wonderful! However, you avoided a significant attribute of theissuein that signature matching is abandoned during the matching process. That is, there is no notion of looking to see if there's a better 'signature' match. As I stated; the import of those two linux function names blowsawaythe other signatures. This seems like a half-way house, but I cancertainly/imagine/ why your compiler might choose not to do that.It's following the rule that name lookup happens first, *then* overload resolution. Signatures only have relevance to overload resolution, and no relevance to name lookup. I worry that if I start breaking this rule for special cases here and there, the resulting confusion would be far, far worse, and would relegate D to an "experts only" language. I think we're served better by simple, universally applied rules even if we're not happy with the result in some odd cases.Perhaps the most serious problem is that said issue does not manifestwithinFileConduit itself. It's only when a call is placed (from some othermodule)to either read() or close() that the compile breaks. I thought John Reimer stated it rather well in his post (7/24/2004,12:41) on the subject.By importing a bunch of names into a scope, well, those names get found in that scope. Put the import outside of that scope!Lastly: You, and many others, are acutely aware of the problems related to forward references. Placing the import inside the class scope is currently the /only/ way to resolve some of those. Now we have to move importsoutsidethe class-scope just so we can call certain methods therein. Do you seetheconflict here?The later DMD versions do a better job of handling forward references. If I have specific examples of where that still fails, I can work on that. Putting the imports in the class scope is, I believe, the wrong solution, and even worse would be trying to hammer it to fit.What I personally find strange, Walter, is that such conflicts just don't seem to register as valid problems. At least now we know what the compiler does.What I interpret is going on here is that imports inside classes are attempts at working around a forward reference problem. The solution is to get at the forward reference problem.
Jul 25 2004
I'm somewhat loath to post this (for a number of reasons), but will anyway. Here's a revised edition, with some additional clarification in the Interfaces section (the grayed sections), some minor example fixes per Derek's post, and an addendum that speculates as to what's really going on behind all this. JCC makes a very good point about trying to address each of these in individual threads. They may exist already, but I could be wrong. For those who may think I'm just having a go at Walter, please consider how confusing it can be to have three individual non-obvious issues within just one specific area of the language. - Kris "some idiot" <fu bar.org> wrote in message news:cdsd5t$u5$1 digitaldaemon.com...Attached is a small pdf noting three outstanding issues ~ each of whichhasvarious bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.begin 666 The Three Sins of D Name Resolution.pdf M.#D M(" V,3$ "C8Q,2 -C$Q(" S.#D M(" S,S, (#DT- M-B -C$Q(" U-38 "ET*96YD;V)J" HQ,2 P(&]B: I;"C<W." -S<X(" W M(" S,S, (#DT- M5^ (IM0T`.Z>6^1QE7WPP5%5#C,^H$FHN^T6V>$BS3B5_YZW`"1[B:R)5%*S M0>"MW]OP]\>[[W[4F=#B\>FNB"NC*Z' US]62B3X*!Z?[S[)7]W+83ATT29) M92LB8Z2Y%S]/QVB3IO(K+RAXJZ1*H]_$X\]W61HK761 \+&YDSH2C[\COYSY MZ3Q61:F)87 &CGF5Q#ES?-P[\1B95.Y[Y\0_#NT NB?Q _C%/COQJQNZXS0> M!6Q.F'L T*/!\.O$A$"!4J+U\"78E:VHQ$;'.JDJ]-DG^8R;'(C=P+ZRE*U% M=9Z).TJ<Y?(5"%5!6]"F1'2 .2X,D%?R!_PH4=92VA9EV4UVYV)8+K3\:211 M>"M)AQQR+5_!*TGBZ?%_UWK%8"L(`![TW-AP%ZP+<.D7?#Z!$9!HDLE]=W+L M#D>".E9TLEKB0!L%*+'D'EK\TS7WM$E+/)W+MD92 ?!:-T^5^$]M0\9DF+0H ME\<NF,W(VTB[!(7 X!C[J48DYR"?[9V ( !I2+JN7;GA*RHG:CN,'!0<GF+P M`=JRD$]DB8[,0]*%.%D[_]01#GV M3"0KRL,01!Y=M*5'.]\"_ARWIM2KU* I,DU.:>CD:O)2%9(DIKN$+5.R-"=O M["/CC4P;*-&61J[3=+**U(PME&>^=/SIH'-)] )+>'/RJ?AWZC+J\3[T1AAC M'6>I&3H:/6X&3J2W8+/4K3\<%1I*H7.*"]5EM8K5) U]`G5 H#Z;ZCB'$'M[ M.SVC[T_\;=7\A7S=M62HW'O<0VE5BB$'78-AUA90 (TGVX7=/TQ4-: )4AQ9 M-)A_7AVZAS(AF^T9-] _G+ "%KS-=OMQLW>VQSIF1YHE?"+G*/ EF*M\QUTR MOYH8EJ-;^N39A#NP'F0`)R GA&F N)P&TD+%J< ,M#XI MS0^9RL]/8%Z)+P<9$U>YJOP9?H;!(RUT&&0^?AFQ4!UQ<J'J/+PYLJ0P."5A M9$$+<FQY99_0X-T1ZCE [?70( ; -^T!%TXG-P[BJ<?6-9/"M +G!8S6WOH0 M%5M+J<IM:NZY.'/=P^8&FBX"`)?)WHT4D$Y0+N;"S/%++EE#QN(D]KW'5PS: MT%\N^AUJ6;XQ8J:)BE7)VM9'BZ4-)$+'BX<.V;0-VFP"-ZW06^J4ILI_DS/2 M2?4.O]"^!BC5T%!F1O:??A,-=B+#N- M,]W$=7P\H$;MA%R^8+C32K9>^;"VHC)O<:#N8A0\.>,+%O_H,!U^N.F-%V3Q M% 6HVSL\%O?DCYGQ'D]<^>->T)=AA <8#W M48=;J'^&`=0`DGAL>YF[VKFK>>VHZR_IMB0]RW[8M*MUGW<OOCEKF:R$.%V$ M;[AE- "=[=<(VI. A%_$T0'*!SO*7/?(R(/&2D:,KF+0I#KO2]:C:TD20&= M4[8?,GT/8%>C\]FUUQ$[$&Y>(*JQ5:*FY<: *?#B#TO-;L =O ]JISC9`X9' M^>;Q=T9_I:"K8FO\0CT[=\II=OON[OKN$>]2Z>:29Y&:K_0N+S.QOZ0[D;2\ M08!:=(B!>^[#MQ,.0)FYM9.8[-J55%-/'-)DX5!CCV9"?(WNR,-)JOSE<+-T MX00[`'Y+F98(QGQO3>F0>;>WIZ++2SJ8AHDS--MAF(/ ZFG:Q;$2>E.^YL2K MTMO?]_FIS4]19W?3>$G6O;B>KLDZV_ U^(Z'H_/4^O'Q[K\3.>Z."F5N9'-T M<F5A;0IE;F1O8FH*"C8 ,"!O8FH*/#P*+U1Y<&4 +U!A9V4*+U!A<F5N=" T M+T9O;G0 -2 P(%(*+U!R;V-3970 6R]01$8 +U1E>'0 +TEM86=E0B O26UA M/#P*+TQE;F=T:" R,3,V"B]&:6QT97( +T9L871E1&5C;V1E"CX^"G-T<F5A M;0IXVJU866_CR!%^]Z] WIJ Q; O'K-O7NP`WI<`60'!8B8/%$4=.S+I):EQ ML2:*96I!X'I[(U08K/^8["<5[04_L$\:YY';YQCJ3-1=J')\3$77=T&X4E*+ M;+R'[S*-10W;&/& `JIMP >*04?^GP3M'L^27<-.95F4JNFYVBHTH"K^V3IQ MM( %78"B8QUE9BH`%<MRT;2 ;BK>KY)69J%2>6I";457O44?HQ:KG3X$T;GK M,%<4VSP/5C*2&G[!O[[ SIFH^D.S[=P\.$>Z/(?4)LJR(,EM9.D HJE/SU=] M4UJ:-T[_(B+4!MQF?2AZ>DR<H][BFXPO-(^=)Q,TCV0_?SSW>7,*;2J:IXXD M9*)X*IY#DXL+ =JOF&"H1PQI/1AA%VHU.LH 0TYD8-AL\*7KVZ*$KWJ0O2&A M7;4J(8C F%V'P1UY\&UD//;68W^/XG/Q52D%DRDP07T.U1;"9V632?PEN?CS MS '(:A$\I/0SQ ?.C\6A>4(Q&7X`*>!B?*"B/]88MGO>Q(%S1 3Q_$9.S %B MJNZQ*D._"?*"8EZ V&<93P><4-7.8M9#WCZC3K20B$'E\U,\M4><P&/HP<JZ M>* =>)P(;?4((P!YOVO:AQ#L[^-W[L-ELZT^ 9Q,,Q+-&5[ \Q_/Q&XDE;=F MI680>-O"USU-/Z-*2<(`CNX`WPO\L6+K 7<N4[6( 1R=$Y#XQV_X*QUA;GEP MSK P0&&+^*)&B>C.VRV(TEZ(.PSZ!T5Z$D]\-!$E4NS*J#FZ;;4CS,J^(?=L M9Y -OE>2+LY+`W $\-FJ+=H2?<*"_0-:#YH6WQNRUS8H KIXP Q1!; <.+#H M#J3M5Q7;5]A#Y3&QAS5$'7?GTZD['/N_>?Y(_((H3^+<K>)GR'));"*;,(O\ M!F[<[9Z/X%?W=5^UNX*<M I^;FJ*R&[0XJ6$:;,T4AF+NJ\/:,$*G=%.G:YV M_I(K\*D/&- 3-+SOEI1C,NERC$T7P, T8Z]L&_+*!Q=M$D[()Y,0,\Y:>" 6 MIG[JT9<[,HFOHZ4_A%8*/M+495OUE<OT)5$IN8R<% /9!- \'ZW[2DPE&%/6 MYE%"'BTZCHVK25FK%,J=<<%0B[#F[H4-A<H5?!8XPK8JJ3 L6MBBJ=DJ2GQN M6GH:7/P!H7TD?JMN?>*3>93FR\RW)Q2_$\QUT!^JCO/^,50`+FN0H 8,4U%O M`Z>"C[5/[Z[D,/Y5$FE?,==]"(F'ZDO8#I M_R6, 96,,7PN*?E<WU''!L4<(9!!SHZ\D$;H3_!5? U_<M"0!#V5(/Y'HF$[ M%6DPF'.Y'ZAZ5X16+8G>";S0U1WB!5VA H&,U7Y(Q?)44%'<$7L%")YT)WZ3 M5N]$,+ANEO %9:\?XY?UC306VS6=4F[0&CQIE4<2PC!HJQL)[D3E_6[I:W?K M'[F;3G+L1ES7, ,(3 :$WP:?$*K$074+7H?^/A[VEHV;BO:OL>T%=G-1/\+. MV:$UR(AO(!T1]U3U6-B/N5Q#U;YI'+.[]QG-4<Z$$I[26'$<BC0JAK66KF^H MN_<5"&Y?"V'I4C=CE6 =M-Q ONA%TD\L/G!QD!DH80.5CM7KDLHP&M]PB6!B M*)]G IQ6HUTCD$Q-A80:\/>*(35F5L[P90$ QZC3C/%DD%2B[")/<\U5? MZ MND^6GX)[="V 7[-(\Q](4C](G4O>Q-09*_-BZKR6&5[(`Q^H1]Z3!^9:OU8* MR>(;E=6>-A>=OK^U-/'LWL-?3FQ()ZN6MST084S\`T- 74M7=C:_*'DA$)'P ML(W[G>X?$M<HD2+[0\_W`9M7. O>GCGHT;T0HYMDTNY1-S-F#VKX M`S9,E\0Y7A[A/4T7/!.8Y^5M& 1\UY\WU.!L81? Y4>Z!H9GC2D>$*<4;\84 M_T!W3IS-3^3(WZJ :QSM`L_^'XM8KNT*96YD<W1R96%M"F5N9&]B: H*,38 M,"!O8FH*/#P M=', ,3< ,"!2"CX^"F5N9&]B: H*,3D ,"!O8FH*/#P M"B]&:6QT97( +T9L871E1&5C;V1E"CX^"G-T<F5A;0IXVK5968_CN!%^[U^A M1QEH*R)U3QX6.\!N, OD0-+!/NSD ;;H8]LM-71TIQ'DOZ<N4K)L3V:3:0P& M+9,46:SCJZ]*'Q_N?O>CR (5/.SNBJC2J IB^">/51PD^! \/-W]$O[5OAS[ ML%VE<7 ??/IQI>6'&X&561%V+%,<K%6D,J5(IG^13&F4I6E*$Z5*<>*7\&65 M9KS#L8:[9>$&=E%A]SG\O IN;W4^]F\WIJ,DT<6-G7>KM4YG( ?_Y8P?'NY4 MKH,\S:-$!ZF*BCQ85Y%2515T]DZ!/F/4[6ZI[(\/7]0W;9J445FRPOOQV:Y2 MT%RT:[U22;C?LW!K4EQRY<JW9T#XLD2;YG$%4J5)BN>M51+E!<L?1U6FJQ0N M8P3D43 /+MS"C[0*]W; AS)\6R55V(X=3.:R<-O6N&>JPV?3X[*DE)=Y<QC1 M%:QZ0J4]'U<P?5HE16CIU"0\XH\>5REZ3]&A61S:!E_OQPZWAZ<W< DZNW!G MGU9PKH$ -?XH,,1W=MVIML>WE99*</VG[B9V0ZG%7 774-\RIL JS*,[ID- M*O7M;%!FD1+H>$(=F&%[L'TP $$^-8/M=G %L[7!`1^.K"%_B?O !/?*PT<; M%>BXQ!0) &\0^><'?46H*5U&>1ID<8( `6!:W8(*E9(ON)4$+;.5_X-"TXHV M^0W8S:K%2?65<'U;M;? ^MQ*\6_"+N_U/H(D=-XG E(-^5,\\D_M*X2U HLM M=FQJWF7SMLIIO(IGF)?*R-F9.8BY []%OD3'$M&Q&? *&2)41&C'$Y_PU:*X MA.L*X+KE5^K^? EEJ8[1M]\GG:0JCI2P$ 9L?Q6X- '\$^H,]5F&] F- 5B> M^?*5_);^8>(/1Q3AA>[7<%J2M\UTH;E87A6S75/<]<)$<1'I]XJ5!, FE5 A M _0!T)?GMK=U`'(FG&,!>S8L[G&ER["I22//;*N:TR];)=AA*'4MI5Y*7[2- MH<G==!&'/?*8/*33$&-W=*SW*;D83L; IWJQ.IBI6)HI8<*:Y!/%!(&3]M&\ MW=/1D"!:V0E80F?I.G0<4*UVL,UP-*?3&XTH%,S*:6 QY "$V4Y%G=W!W=KN MV.S9D0T%%+"[)W,$!M*89DM$#A35O M8%Z$<H*]3 &Y!I,H\)6>;]>T= A(F7H;7(2*ALQ>H"D4QB+9`"4"3/\97=>2 MS?: 44$6`$<S%)8U*Y3>E;<L*WR")T2LEI8U6[J-<P_ [^S"/;9F[*VD-4-Y M,0_[P6P?"6<!2E^(HU8AH;KDW\(=U[7C_H H*PFT(7BL&3B[07S"`8K/RIW= MCEU/&-M*8GXA_HX2E)G[ ^ /49D 100O&TD$QG2$M1,:>I8K7)[MQPWBTH(. M7 X"`4KU8 DP93ZA$"C,,0G<78J5)_0)`502!G(7Y)07G+24WV2]D?U(.XQG MO947>E [C/K?J)PYEW0JX*)D3S8BB?B*8TW2*WCS$YMQCJH*O;T1AD0E%3 % M:.R \VQO&0*Y^Z$;M\-4\Q$.H1?0+SI_F3V2!650<<67G")%L4N"RW1[*BD5 MN,E91>6*0UPYCX[)$V'"3*$N(QQ_-"+#USQG`PCTV&.:"J"RA&!L"<AZT-H? MT%GIZ<3WJ,V&H>V\< 50*R=&ER,$S[,BF3N=8Q:G48D#Y3'+ V.>G5.H.3'[ M,^E*WK]![" R]F">X8R?BRP]( -O939X[ RT)S+GTSE497P;8:BMB.FNNS!& MED7)>]%OG::^"3B'H8D 0)T&TN*#H] S/N[K&]=MP76 J0TKIIYLA<&]L1.% MB%CJ9B4>>G-)SG;OS:MG]C<#VJ1 MJR7O0U58S"NY_"*7G&5-Y&J5N]+6YY&QGA)?SE2G9(Z3A\\CZ"4K^*3M/9?X MU0NEQ]1A>1^G5V6%R8F4SN6(84] T"\F<M*WS-N9<!*W* !YGYF*7;) ==GS M6"LPVAP=H*3*8D8 XI5E'/Z=4GDM![B6PZ'M.86X5VWW1$W3>UJFKH'1C%9F ME](5\9<[,JJDILG[N+HJ,LPQI'7GIP`<',/H?J6KB3 =]",:I>+;5)>7`2)\ MJ[VX;(E6\0(9`%B6+5)8PV3G_,.)DU ^5A"ENOHE!?%HR:V5C/N*8])TH6?M MXF_MWSE]`KQL3U[AU>Y;R_F] 4?EV)*"ZNLP]D1Y:HGR+&S?J$ %NV WXX58 M.#A&`V:H6S9(OG2-_.;'M *CC Q/ <(0V9F![F7I4]J,2I 7G&[Q`P(V?$8L M.YCG'BLDC S8A91E3E,/G[$E PPWA5KB8+]_Y6FMKB V 12(QPU&I3($?,A* M:7I>/T[D5?,GT?6&&R6H7ND?X3YCTU#RW5)Q"!=&WRG.!:IES[%YI=MWG0%5 M6W%J($T+Q!(*(6H#UNXP+,1QL/O+>,_<=V2FK^0$;%0,<J9L 4/44B'YUT_4 M"Z:CF#LV5CIAUYS MWR#T1 M4N<8,LWN^"A-(XWM`D"=>G83J9_9DE/KB+PCN^P=48>)Q '3<2NN/Z"'$OPI M,"!2"B]0<F]C4V5T(%LO4$1&("]497AT("]);6%G94( +TEM86=E0UT /CX* M=& ,3DY- HO1FEL=&5R("]&;&%T941E8V]D90H^/ IS=')E86T*>-J]6$N/ MVS80ON^O8&\4L%9$BJ2L]M0`;9$"!8K60 [='F29MM7:HJI'-ML _[TS0TJ6 MO<]LBR+(2N)CAISYYIL9OUU=O?E>:";8:GN5Q;D4.4O 7WC-$Y;B*UL=KW[C MJXBM_ICI$Y)TP0/T9$D>!SWV8R13WKC.,B\&MF276X0T<29/V[BK#W>/*A J MBU,S5\*BA4YX44=2A7=4JW ?+> >MJV+2 I^B-*,+TI' W7?%B7.IV''-DI3 M[EH8,3-Y*;^+5!(&=A5*^&!Q&&RVD#DO#Y$2O. Z-- UC)F$=T45P>J-WW2V MP \=4<S0];A<\JX?UHS.Y!5NO.0-*>N:HB_W;.O:8+Z%BK,LS]E"Q"*%)_ " MFI=\31?<XBC9(^.6]32SMV1A,J'QUVA UM*;UK;LMHI K[H#RO*TC9X4:DY MVALI90<S( <?TPK#FV MM_EK(->V]H /2Q#RKKT.!DX(+'H$BY_<3RB&$"<?3H=2<)8]GL -APU;6S8 M &"AGH&" 2V=D. 'GTU0]LX DQG"?#Q$TZ6RQS=9;3R+OO9MGBWRFVF/?>\ MG$H9I[,],>K-^7N\S Q?>S><;#RW_<PVBY,KR18C,-"5$#D=AHD"2A ZOW;= M3S? 5Y8$]'L"Q2'E`T<H<X\F!? DA%LZ.0_'Y+ >J&PX1CH+7-72!L/=-J E M?#WT9^$V8>",,QBPNEKZ,"+X!"Z&`X$*N,^NGA'$T-KNZR 44IW_;UB[0V<L MG\CS6B7>(^6AP/N"51&P['VT6":\K7J+_F[/Z$$(RNN?B&!5K)52-+$4RE\$ M-YO39M8,R/4]N^$`\53 V\<(?' 3L4^?)\D0K8E\5L! Z=FAW>L=1<1'?+\G M)3Q3?%ZS+4630P2UK$ YAP.+/"RU`%B6K*<\WUCZGFH$<%]ZYM?/Y->$ .(! M]% TI_ERS O$083P))F',J0S'YL^3\!0/D+<A?FNL66%5BD.4UK[&X-J*7RZ MP=0#E- M>R1X0XR&X/UN=07,BI53" \#QTCB)5ODL1!P_M9>"3 8H6![>>JWJR</#G4Z M24O=$_W!TGMN&/'MW?!Z>I/0`$\FA ">5X2!M^;5,0Y! 5XZJH.:*K0UV%PA M7YZ3$YPY"]2UJZ?;^-(!5RM?:[2SCFW.UA,IPLA[XEO0ETQ]\\/D=Z_'H3(? MXC&0L!R%7,P'*#H *7M,GT+E"12E,K]410E2)O>*R<>A(\2(.GN"`U6JB9CG MV8L*]=2Z KMJ%W2<.K"I$\G'3F1J^LY:V11*T.(#NJJH)O7%& =\(X]KP$XW M"$5Q: SA[KQI?7^W&4I"6 I7H8X)`IER.6R_);8M>E(5BO'0-(ZBW9HT$=3_ M24BPQMC0 <>:$;>+-(TS<=D*D ,\2QRQNL2?=6QW$\5LA=TDA.6MH]]8VC]9 MR*SN%K-RSG>AC2S1K/X7AM!%]I6K7U7.B,Q,=>._+V?.LQ1F7<B/PF XBLG MOKR C/H'?NY/D0IE;F1S=')E86T*96YD;V)J" HR," P(&]B: H\/ HO5'EP M5&5X=" O26UA9V5"("]);6%G94-=(#X M=&5$96-O9&4*/CX*<W1R96%M"GC:C5E9C^/&$7[?7\&\!"U Q+";MQ,$L+TV M8L.P V2 /'CSP"%[)&4D4N$QX\VO3UW=;&FD36Q 1R3[JNNKKZJ_>?SPA^]U M^_QDYT_&F"G:;&&R&FW;G/%WE:MI.&U,J:P\/C4;DZKIL,E*U=*[0OWRBWQL MI F/M)PV::7.\V8+#X=-6JJAG[ZB,:EJW+K+T\94JCUN,L,3M:)/-4ZI%)VE MTLK^MC&9.MMVMAV\,DFB>.&!GFK>H-]OTEK9$1YR^2Z+-;"!5D<<A&^*6IWP MMYWW0P=[D-*2:*MCG=8U*NU7];Q)4S6"UDW! V%B)1OAVIH.5R4 P]F.6Q0A M<;(_P)>Z5DM_W.25LEZN.E&=Q9& I9$D 17/>%ZM7DFG?&K4<^5$V%O\,%J2 MJH_A4UFKQSV.*3/5HF6,.M.Y2$ [XDXIGU3.B/I+5_W!V5;UP:'.(N?K89.7 M\9ZM><PK"4Q*2%T0T*IG-FGIO*N9[0,\>^4T=+1.GCH+AR\XY- TH!GQK!.' M75R+D.-GU"^^2=2;!6UF/IXAG)OI!7Z \Z+[&3 HJ(._?,0_I>AF)JV `R\M MR9FGWI/P*0&A>U+%`(8DMP'?[0</8A6"&#HDF MR4<JY_ %V)QQDK7K/ %C_(BOAZ:;.+B<3B6DD_I=L.E$(JLN>?WZ?5S!*Y=$ M]CAO>+OM."$4(=!,T0F=3G1EHV=< G&.H()V>*+!1W$=A\_D!''T]1'_'M%X M$7S T-Y9_%$Z:(UZ/,T65OMDDES.!?FRO,Z7J4[B*LKK"OZ%E*F^6?"_X_'O M^\/\NR]EV;S4+LO^!?1(:19/CWY3ASZ+"3(WZ <0LQ"7].X%5 =-3'M$8/)> M+^G (TE&4L#I2A41T8,PGZ"\M<L+P[20<;,4[0<)"C&84QF/"[+E`Y^93V5R MM+P;"%LPKO"D'_K9CL\8VTUK(TX2P^UX&.T9< +B9;&>V.CD&GCPE4 1Y!/A M`&>![ `?*1II'7+[NKSV79P',=^.=B9YX&U+2!V(G]3!GNGEGBMR0M19'[K5 M=4:ZZU*9T7$!/I67<2X>8G\#O MGWT6=7FMDI2_.R ^](%&5X,AU 7(!P>9K)44?FT)OQ/CN'$TQ#LB/EQZ( -A MD&,EX0+RYX+R/1$A(6/D#S[U91(-'I%N.O1Y>(,= :-GM>> /:J- !8H%VGL M'8XQ7Q1R'#IZ?V&1%7IAW5<:L%O<M+TG<?3X>YJI484OI*I4[9H3BL29'L:> M'6#CF57/>NA7*&GF`] M"GU RP=DZL0&F<(P16'G:U_X:?7P O.M'T%:I=G; M)X A=+^. =I+=,MU^/1-1PETK1W0\;[=3O-GQ$ ^O9#P2ZFJ0"I//E$JR=2> M^3)%14RG=2KG.,( 8J$ /Z-FLW>:U1#UEUR%A0HI(E-/X'& !* (OOR"3^)R MP&%&B?Q;2 ''!8KL_DM9/--EK 5 O]Y(!9AA^<2YRS$CVZ'GYF$!AU4(\\V& M)A!/X_!B>SPOO-NOM0O4M/>X_5JK`" U8XN&SY60%/8>) ,?20W(XLZH'OS1 M7V1M$',YTW&940BI ;W1C/,!M<'\%+T1M/"SD*&4W3 M+U3,*]()V(N'T[3A MV/3OPQ/0FS6\'=]OSF?;H'J\V]]A+4U')7QQY?J [HS)Y/"$RU5Q67!?P7A1 MLF&HC"[5^$+<KZPN(8_M,X&QP EVG"((NFX[3S,+VCS)O-CW:8!._?6(!3N4 M459:* QH:U\J<9+[<E#K4 MU-!!H'7+Z3YGA4FF3N(BXTG$4SU5"A)+]5XY:T<2Z!?"9"%>595"WB%\/0MI MD!=W>ZKL/JW=/C4<.9U,<"&]?:9^U=J!10:_M $=*^&:4Y>2<; +>$ *VN]< M0^NC8R:K2;"&Q*8R6IF)2PBMR%5W0\"5 ]2 *I*FF+!/1Z!0XKM=&L8^$(J2 M]N_E?DG717VM7=B$^V1AY5W4MZOUPO4/0/RW83D*+5Z[U) RLR!B7<JZW>'/ M'HGHQ ,J I8RG0R*HX_,`8%Z`'3UKA W*NA^=(SN<+(>YPP<!"X!,&=^B>A. MIH_F/>>FZ.1X12K]B1%=!Z3Y?AB%&I+6N224`F+%J?H:IW0"& =H7Q%*_2E) MS'K5PP1SFBE'N(Z?B[R0(0?JPF!Q-+]T`2)U1/J^CLC7VZ&6BM%<0B D^F$V M<DV9+U"87(C)PITV0CMP``2EF&F?M*VD3ZH=/?39G9ZKF]&)=&IJR#R=/-)N M_T-A]7LIC%SY]4* Q1NZ0+V0B:^4"=1$>N 9]M"%]W$WN[GM(R[/4N^$;JPN M\RQ! UDO1$VEUXLWA$,J-PWX)4,9TM-,\327L8Y8!PT#E:LORYF^U3X"3PBG MP>V1O*?-L(7"/["#CYZHR M\/SM, )JS])8(8US^\1PG\#Y7N4F M:*P=R<#QF:_H5 6"8NCZ/PD+[\M1<M,M>+":1\JPS*E/4A;Q!&VRE3_>Y7'& M,[.+ D")GU_.1V![7TCV]D>#I#Z$FOQN8N,]D" ]L6+HR*&Q*E-'B?.^>;H M`*E\F.4FYM7VT7$87B W-%_H]6<&RHQ (153Q^J[QP__!;M2+C *96YD<W1R M96%M"F5N9&]B: H*,C( ,"!O8FH*/#P*+U1Y<&4 +U!A9V4*+U!A<F5N=" T M+T9O;G0 -2 P(%(*+U!R;V-3970 6R]01$8 +U1E>'0 +TEM86=E0B O26UA M/ HO0V]U;G0 , H^/ IE;F1O8FH*"C, ,"!O8FH*/#P*+U1Y<&4 +T-A=&%L M/ IS=')E86T*>-JU65N/X[85?I]?P:="`M8J29&Z9(L"FS8I- ]IT4S1AYD^ MI-2J%!+^^:^E%"E^%;>/-W?1/]W3OM^W\2HU42-BK2/]1OPP'.*5,=$++TAX M*B-IXO^(VQ]NK$FDRBT0O%W?1%DL;G_&^TJ^3VFZ"SZ4+$0NRX0N^I.412JE M-67TM^HQ-FE$AXWE(W3"R*C?QR:+'D=21+3JWN#C3/-: S]T&9V(Z*Z*M?'? M_05_I0U%5#W$.HW:#I[EM$/Q/5I&FSC5T=#A8AGM')+HB&E I6Z/+)B7";D' MUCX,1W\QRD=ZEF*E$I66)>KY+NIQ)YB!&+32Z\%Z49 !7,GI_M1+L^YCH.G7 M*Q+4L ;<:=>N<:$H< $$.M6[/>JNV7I1O0X<"DI'R^BAPA^LR)K6LJBA-:+A M_-(SW%YZIH"H?:574HJ7I!ZZSC4G^E6PAA)ODO>XO8 6&K%!(^O6H0ZT`NKM MJ "M) M8G6 -N' =K:;1\PX]">3V*VK!3.?\MM%EM&25:9E%#Z0$OH1/C63O MHY9\H/-< G/GY\Z=9 H<.RM4DJ%[1^YC59_B:Z&0%EEBIMUWT7WLY?2"U3MB M>(G!7P7Y8M $/"5>"N\+K"?7HQE!,QC+0X_Z!:]O-Z(ZQ-J.T0SF(-7/ A4. M5[ST1/2V ]]!-H7K'02YBHYC8(Z.U3+3=07WQ>P0P.<!69M'VB5WF B GQX[ MM"HXN7,8)67A=7UJQT [UW*9LI)1 L* 7X"-!Y1519/B"&S L<:H)?[1> <4 MB?3<]B=2%3^H7<?ZK/:XHSG$$"7!"*5<Z$0'G1 /:BZ3A.#M(!0EQS?$,C// M^7,"9?HCZI:,WIS `7P,=$<O)J%2C[6L&;*RJ#QD>+Y&?]0018GW_E2L=*++ M48DR> I ;GV:Z!B\R.\NQP7")C""1H54T39(-LL8[TF$[0Z?Y8I_,41M]^B, MP6#Z7]>A+MOQS&O\S4VB%F>8.3;8#DWE.O))Y F!-X4X%11.`'! BMP#Y[:9 M>2"&#V*B3<'G* #Z MJ!F6 4;;G#I&Z/K4OZ75[ SCD.IE 8KP>"'0)5]D&*$PI?J'*[F"741",/XR MD%TZ`FV;+IUFCG\0"RUC]U2 V=Q7,;XTRHK1F*^=MX="$SY\D)W715!ZCF51 M'C:=9Q K0WSWPP.J`2T'W)/E=+B'\W;5K"^C-,D_*MF4GW,:>^XS5 :P"K ` M!+[[" 9N4-6YW_/C5%2S&*#Q? )%H[,T<^7602,X=$<!7EOPC_^C=?.MNS8 M-! G"%ELDX4-SVI2N. P%GL4EV\X"HGPE'4P1=]KK?O+?G6.1%A.>3T"&U1I ME\9CGRJL)]GZ6JM'=,XBMT/O:)\_ T;:,K*8U!>"U6%?]5<+09WGB3'3]KO M+V SE[. )TOGY3Q2=6A]EI[G4;M(,G6.VEQ%-''H/9354]]GTT6 +-NLL24* M/,!/R PXA[CD%RJ?VBL[:Z\*K[;M4&V=N ^M[^$ESB1V>>N6L T4V0W5*)RA M!*3U(TT:IHIYJ,F+1"4VCNNS`3>8"'KG=XS6U XF(][-*]Z_-S-).JBY=,GL M49V(<XWFC5?>LD?V& J" P<<CU7'MS >^BZ'4PLV43_CPM"3:H$CFC^ A?OV M !7'K#RH.CB6A6- MX$^(R:SMTW58+J4P4"+FWN^J`8$B'<<H^YHB.81\2'"SPM',"D<#SO<6_5Y0 MO456.'B]==C,H%76XN$%6X99MP7.MB$?.4 #D4':V3=(?_O-;PY(%,?:1)H0 MY^;;V\\RA*- DV:8 XBCIQC*J1:EVP/>H ,-W;';`UQ <"!>B%\_^< SB34F M`($5BU\9BXG#MY<\X-.9!Z26TLWOS*,Q26:^S G _6'Q)/9+E2X]5EYPC,^Y MS&?R#T2-+FT85_^+`'7-^1XB]*RJ1KBJVR?HQ-]<F8."$X8F/XQ!BF D!UT= M=KPJ.O*,687A)R8 *C^YR2!T18 !M&V'<>X]#IU]/S(TVVF4 7.LY>R+6_ / MR&#A&R" <RKP9G,`8J%8SM<O=1OS 7DB+B;H]PUSU ^/XSL+R"R<EK-775O& M[R6R_#SKX9.S/*VCQ1 7N_(>B F0V#VC/JSU$X+^M-I0PSP:("NOIC*2/;-7 MMN,&T0_=T \GW5& K)G)\U8P*U_-\T)KSJ^ .(FOV\;WOS7Y7GK6].-<(M2* MM/0TFR7PVX7Y3,O[;\+6IF%1&1KLT&Q?<BT>46YW?J XE6('/ZXKH _NP".= MZ>$L_.$:YL:'9T"58'?R>4=H-\4ED("8-7(V)_6O)2Y$K)[>H9U7Q"OL^N&P MY2 F=NMJ49'J6>=!Y*<W? `Z6,JFOGV"4I8Q`8X\4(%]V;<6H41C?SC\P/%. M\[)>K/F2>J"Y3 ]D>:XB3F 8BSO:>G DBS:GRR7W/PX8+*[JG5AWU;. ^&L' MCU/\;N^9JOYQ[ETC2Z2C <,*?.Q\:GFAO[(&"EF59SYU1NKZ?,$6V-VI7&%' MAGL33HG*)!(5M,H2E0<)L$B 8NG_^8F#JE M-KZ<\")F():T)*;_"B>+,K'ZHD:P(56*MONOT! 4!ML"RN[O,9]N1-.B<Z'- MP9?G_< Q=(L\IH1\Y 0DA0H<#ZZ MEN& D0L$-L DJ2S%:%NJEH:$1(W4&^(.W.1_.<*WB IE;F1S=')E86T*96YD M+U1Y<&4 +T9O;G1$97-C<FEP=&]R"B]!<V-E;G0 .#DQ M+U1I;65S3F5W4F]M86Y04TU4"CX^"F5N9&]B: H*,3 ,"!O8FH*/#P*+U1Y M,C .3 U70HO271A;&EC06YG;&4 , HO4W1E;58 , HO1F]N=$YA;64 +T%R M;6%N4%,M271A;&EC350*/CX*96YD;V)J" HQ-" P(&]B: H\/ HO5'EP92 O M<V-E;G0 +3(Q, HO1FQA9W, ,S(*+T9O;G1"0F]X(%LP("TR,3( ,C8V-2 Y M:" R-S T"B]&:6QT97( +T9L871E1&5C;V1E"CX^"G-T<F5A;0IXVNU7?7!4 MU14_][[/; +9A"2D+,);GHE($D) )'P8EB0;\C'6A 3912V;+TPD2$2' E F M:+7^T3_:F;Z3W_N=>\YYY]YS[WTO=XD1D8MFD$3--U1FS\PYU1^&Y1!P8^VZ MN-FIU=7KFZ4;U6E$[CX8C.:U]<TWO'+5"K0_1GP5,6T2BY""OE^37X,E99BI M3C+B;,?77-=7& ;Y/C<^'U0SV..4H^4PJX7^:Z\S7^O) =2R`-_"ET/[&=7 MG =?+9 Y.=I9F\,_H&W(_07OYB?Y2<>[$'E+[0 AO%OI ]W.MY6>IO?8"<1L MI#WP M1'6.UH0LC#AV M2ONE ]+KTNMRL=PA[Y/?E=]5F&(Y,Y6H)JFWJ*V0-BU&6Z5MT^[5'M:><TVG M\: K$W65TC)4M0&5;**=%'96+0HY0L]"^N 3NP[(X% EMLQEA:R(+84$V7(6 M8JO9G6S]2$6/LR=8)SN"6MZ$O,W.LM^S/[+/'#G/59[",T;J*^>5?!E?Q>_G M;G'R=7*>O%2^!;6?DOOEC[&27)&4-&6V, _2H-RN;%9:E4>PHP>4`37.F95$ M=9PZ7]VA[E6[U7?4"UJREJ)- 4S7<K1*K4E;IQW4^K6/]$,QBV(:8]:Z,ND M*8;*Y%.T3+J)FI0:*5;[E#K9G?(6]I14A&_T?FT=.RZ%I %IOY*FSA?SR1^4 M#FH;M)#V$4;ZI;1':="FLT5**^OD"_%&KV45]!4[1]]#SW?Q:72*=M%.MHYT M:M</L3%XUWKY9-:J/"H=ECLDO[*978T5]"A]TG::3<D41U-I"O:Z0DGV!]<W M)W?.-;-FYLS(GIZ5F3'MZJE7I:==:4[Q&I,G73'1,^$[J>-3DI/&)2:XX\>. MB8MUQ>B:JL 29Y3I-XM"AI4>LN1TL[ XRVZ;U3!47V((609,1:-C+"/DA!FC M(WV(7'E9I$]$^D8BF=M80 NR, V_:5BO%II&#UM>$8"^N] ,&M: HU_OZ'*Z MTQB#AM>+)PQ_:D.A8;&0X;>*UC6$_:%"Y(O&N K, GI75B9%7;%08Z%9169S M]Y&082TV"ZW%=_>G9F7VL">J`E9,00^CJL!1*AULB9:T%!8&[=X2"P([G/#Q M"!]_=[]'"OM3&PV[&0[O,*R.BL"E7J]]#P M25EJ- 9IV^PR1<'UIM^VA&XSK! SWVP(WQ;"8DT(6[1D _?PA%+?T<'?4:G? MA-L:1CT\U<P>D5F"+6(9M09&$C MGI9KW^IS*5R;BS!<0889;<3\A<+N>?9" M3%^\] :3WV"/X1 X2,J =)1]2)1]<< ]0 L_PSUGQJP$;T*:-\';(M&%%DX7 M2>G[6VZ+C",EHRYVG%^0XY KZ05B? Z*E% M$ S +V?&.#S:Q<L15'[!(F<. M> M-3;BU<47\ G.Z1W<^X_N[]ERT.7I:>X/H8KGK?2T'S3 GWK[ 6L[%<IQS MVX &7W>]/^(9OC[ =HY *J G57/H]*8J=3N: 1.4*F63NTQQZE+.DB]^B'J MTJ905TS\$%8(Q.X`VJA+[Z4NUXO4I?Q$P(Z5UP!GX,.I2[N/2O4.Y-P&W2O\ M#FQ M ).I72VA]N&^E+\.H0_ F-6;8$\>&L<T,988'W)AW!KRZ4?!J$_[/G OVK/ MMXM:]>UX_CKP2NIV9=!.&7-G8[ OS&?I9< =A8V(V7C97/R' 7-KEW1 U.ST M<SGV"OR[.-F.Z[\TAKF'?&> Q__+W Y8S66V'5\?^^V UUP&_![1Q?[-^2:X M5.Q/5:RYL^ZC\_YZ1']K"$-M=?9HZ&&!$?_?1V/$OHEZ;=AK[.B+P)= .DNU M4C+5ZHMQ.B=*_[] \OZG17RK/V!QE$V[:2S^:[BAS87Y4WF%_=O/%T=%10A) M3-!]Q48/O_9P\4S05H?8(4%/"3H J%/0DX(>$[1/T%Y!)8**!2T6E"_()RA/ MT )!<P6I F1!DB#FNP'\+G 6^ WP%O 2\!SP+/ ,T 4<`CJ!)X&]P"/ PT ; MZ ->`4X!O<#SP M=5W599WK^!99XZ0R7E:9S\JL$[545F-87U6:/<Q5L=Q2S'QF)991655^JI6; M8?&=SJFXAPU&&;MGN\<^$!\EQ :W[_8,<3!(*1G_?*6.:I65;SA.D]D<'% F MLUG=VN27-=M:"6O$L49L:\2QIK+#Y32SK+HU= 5E?-/%,K[MQ?R-=KGE :A. M^<&"FP5W\U 7Z EYO,'\%'=SGE/<?&_J9L\QF5 GQ>)<&(<?&F,`VY6U*&N1 M9&]B: H*,C< ,"!O8FH*/#P*+U1Y<&4 +T9O;G1$97-C<FEP=&]R"B]!<V-E M;G0 .#DY M+T9O;G1"0F]X(%LP("TR,3$ ,3,U.2 X.3E="B])=&%L:6-!;F=L92 P"B]3 M=&5M5B P"B]&;VYT1FEL93( ,C ,"!2"B]3='EL92 \/" O4&%N;W-E("A" M0TPI(#X^"B]&;VYT3F%M92 O5VEN9V1I;F=S+5)E9W5L87(*/CX*96YD;V)J M,"!O8FH*/#P*+T)A<V5&;VYT("]!04%!050K5VEN9V1I;F=S+5)E9W5L87(* M+T-)1%-Y<W1E;4EN9F\ /#P +T]R9&5R:6YG("A)9&5N=&ET>2D +U)E9VES M=')Y("A!9&]B92D +U-U<'!L96UE;G0 ," ^/ HO1F]N=$1E<V-R:7!T;W( M,CD ,"!2"CX^"F5N9&]B: H*,S ,"!O8FH*/#P*+TQE;F=T:" R,3 *+T9I MT!XB#FLU M<)XLXQP6- A7'#V M0I[9(GL:?_&PQ/B-$U*"1B %%EUN\Z;CNYX09";]?7VN$:&M>+?--L'B'+5! MUC2BZ)H<"KJ7'$H V7_U=E-=G?G27-E/F>V:ME$%'3:D]U5[8Y4N9;>[)[,P M9[OU`-56,>0)[S>*(195?3^;P6N>"F5N9'-T<F5A;0IE;F1O8FH*"C4 ,"!O M8FH*/#P*+T8Q-0H\/ HO5'EP92 O1F]N= HO4W5B='EP92 O5')U951Y<&4* M+T)A<V5&;VYT("]4:6UE<TYE=U)O;6%N4%--5 HO16YC;V1I;F< +U=I;D%N M("]&;VYT"B]3=6)T>7!E("]4<G5E5'EP90HO0F%S949O;G0 +T%R:6%L+4)O M.2 P(%(*/CX*+T8Q-PH\/ HO5'EP92 O1F]N= HO4W5B='EP92 O5')U951Y M<&4*+T)A<V5&;VYT("]4:6UE<TYE=U)O;6%N4%,M271A;&EC350*+T5N8V]D M:6YG("]7:6Y!;G-I16YC;V1I;F<*+T9I<G-T0VAA<B P"B],87-T0VAA<B R M1C$X"CP\"B]4>7!E("]&;VYT"B]3=6)T>7!E("]4<G5E5'EP90HO0F%S949O M;G0 +T%R:6%L350*+T5N8V]D:6YG("]7:6Y!;G-I16YC;V1I;F<*+T9I<G-T M("]4>7!E, HO0F%S949O;G0 +T%!04%!5"M7:6YG9&EN9W,M4F5G=6QA< HO K-3EE83)A868W-C-C,6-C83Y="CX^"G-T87)T>')E9 HR-S<U- HE)45/1 `` ` end
Jul 24 2004
Dagnabit. I apologize: made a glaring typo ... will link here instead http://svn.dsource.org/svn/projects/mango/trunk/doc/Names.pdf "Kris" <someidiot earthlink.dot.dot.dot.net> wrote in message news:cduv7v$1e9u$1 digitaldaemon.com...I'm somewhat loath to post this (for a number of reasons), but willanyway.Here's a revised edition, with some additional clarification in the Interfaces section (the grayed sections), some minor example fixes per Derek's post, and an addendum that speculates as to what's really going on behind all this. JCC makes a very good point about trying to address each of these in individual threads. They may exist already, but I could be wrong. For those who may think I'm just having a go at Walter, please considerhowconfusing it can be to have three individual non-obvious issues withinjustone specific area of the language. - Kris "some idiot" <fu bar.org> wrote in message news:cdsd5t$u5$1 digitaldaemon.com...Attached is a small pdf noting three outstanding issues ~ each of whichhasvarious bug reports stretching back into the old NG. Given that the v1.0 release is getting closer, it seemed appropriate to try getting some priority and/or traction. Such things might simply fall by the wayside otherwise.
Jul 24 2004