August 25, 2004 Re: String equivalence (was: the $ token) | ||||
---|---|---|---|---|
| ||||
Posted in reply to antiAlias | On Tue, 24 Aug 2004 14:58:09 -0700, antiAlias <fu@bar.com> wrote: > I thought about trying to get around the toString() issue using opCat() and > opCat_r(). It /nearly/ works ... the nice thing about opCat() et. al. is > that they're not overriding anything (like toString) and therefore can have > pretty much any kind of argument and/or return value. For example: > > class A > { > dchar[] opCat (dchar[] x) {...} > > dchar[] opCat (char[] x) {...} > > dchar[] opCat (wchar[] x) {} > > dchar[] opCat (int x) {..} > > // plus the opCat_r() equivalents > } > > This looked really promising! However, it all fell apart when trying to add > a different return type: > > char[] opCat (char[] x) {...} > > because D only looks at the method name and argument type, and ignores the > return type. Therefore, a conflict occurs between two operators, and the > compiler throws an error. Adopting a type promotion approach (as both > yourself and Matthew have suggested) would probably have to fix this > bugaboo. Yeah.. it would be nice to have the return type included in the method lookup.. it would be breaking from C/C++ convention, apart from that is it really that hard to do? Regan > "Regan Heath" <regan@netwin.co.nz> wrote in message > news:opsc5skbhm5a2sq9@digitalmars.com... >> On Sun, 22 Aug 2004 16:29:29 -0700, antiAlias <fu@bar.com> wrote: >> > Right. But I don't think this stuff should be done by a cast(). I >> mean, >> > you >> > can just as easily convert them "manually" using the functions in >> utf.d, >> > can't you? >> >> Yep, we want implicit conversion, eg. >> >> char[] a = "abc"; >> dchar[] b = a; <- does a UTF-8 to UTF-32 >> >> > Where automated conversion would really help is in stringizing >> > (the original topic; I think): >> >> Definately. >> >> > class A {} >> > >> > int x; >> > long y; >> > dchar[] z; >> > A a = new A; >> > >> > char[] narrow = "string some stuff together " ~ z ~ y ~ x ~ a; >> > >> > and the wide version: >> > >> > dchar[] wide = "string some stuff together " ~ z ~ y ~ x ~ a; >> > >> > If the ~ concatenators could convert between dchar[] and char[] >> > appropriately, then Matthew's idea about the type being specified by >> the >> > left-hand side would probably work. Though, on reflection, this seem >> > like an >> > awful lot of work for an operator to perform. Particularly so when >> it's > a >> > special-case, as it is here (e.g. int[] does not does anything fancy > like >> > this). >> >> The operator itself doesn't do the work, it's the type promotion system, >> eg when you say >> >> int a; >> float b,c; >> >> c = b+a; >> >> the compiler first promotes 'a' to float, then adds them, then assigns >> that to 'c'. >> >> So, Matthews idea effects the type promotion system, I had a similar idea, >> I suggested the type promotion system use the type of the thing being >> assigned to (c in the above) to determine what to promote the type to. >> This was to solve the common: >> >> float percentage; >> int value,total; >> >> percentage = value/total*100; >> >> bug which only ever assigns percentage an integral value as value,total >> and 100 are integral. >> To fix the above you must go >> >> cast(float)value/cast(float)total*100.0 >> >> notice the casts and the .0 on the 100, this makes them all floats, which >> is the type of the result. >> >> >> I think we want/need two things: >> - implicit calling of toString for types with toString defined. >> - implicit calling of toString for basic types. >> - type promotion in operators to cause implicit conversion between UTF-x >> types. >> >> Such that the example: >> >> # char[] narrow = "string some stuff together " ~ z ~ y ~ x ~ a; >> >> Will cause: >> >> - represent "string.." in UTF-32 >> - append z >> - call y.toString(), convert to UTF-32, append >> - call x.toString(), convert to UTF-32, append >> - call a.toString(), convert to UTF-32, append >> - convert to UTF-8, assign to narrow. >> >> If the example were changed to: >> >> # char[] narrow = cast(char[])"string some stuff together " ~ z ~ y ~ x ~ >> a; >> >> then the operations would be: >> >> - represent "string.." in UTF-8 >> - convert z to UTF-8, append >> - call y.toString(), append >> - call x.toString(), append >> - call a.toString(), append >> - assign to narrow >> >> which is better as less conversions are required. This is in essence what >> Matthews idea causes, yes? >> >> My suggestion causes the same sequence of events as Matthews idea. >> >> The other example: >> >> # dchar[] wide = "string some stuff together " ~ z ~ y ~ x ~ a; >> >> probably causes: >> >> - represent "string.." as UTF-32 >> - append z >> - call y.toString(), convert to UTF-32, append >> - call x.toString(), convert to UTF-32, append >> - call a.toString(), convert to UTF-32, append >> - assign to wide >> >> interestingly this is identical to the first example, if we take Matthews >> idea into account we get: >> >> - represent "string.." as UTF-8 >> - convert z to UTF-8, append >> - call y.toString(), append >> - call x.toString(), append >> - call a.toString(), append >> - convert to UTF-32, assign to wide >> >> which is better, my idea actually causes the original behaviour :( >> >> > Instead, how about a concat(...) method? It's not hard to make a > typesafe >> > one that can do whatever conversion one desires (including calling >> > toString() and converting as necessary). Hell; you could have two >> > concat() >> > methods: one for a dchar[] result and one for a char[] result. >> > >> > return "my granny is "~age~" old"; >> > >> > becomes >> > >> > return concat ("my granny is ", age, " old"); >> > >> > Is that really so awful? >> >> Not awful, but IMO it's better if we don't need one. >> >> > Regardless; I think there's still an issue about toString() not >> handling >> > dchar[]. Although you can utf8 encode the content, that's hardly a >> > convenience, or exactly efficient. >> >> Exactly, so why not implicitly convert.. I can't see what problems it >> causes, and it certainly solves several. >> >> Regan >> >> > "Regan Heath" <regan@netwin.co.nz> wrote in message >> > news:opsc5nxehm5a2sq9@digitalmars.com... >> >> On Sun, 22 Aug 2004 10:11:10 +0000 (UTC), Arcane Jill >> >> <Arcane_member@pathlink.com> wrote: >> >> > In article <cg68tk$11on$1@digitaldaemon.com>, antiAlias says... >> >> >> >> >> >> The problems with that particular approach are twofold: >> >> >> >> >> >> 2) more importantly: it doesn't work for unicode strings, because >> >> >> providing >> >> >> a "dchar toString()" in each class is not covariant with the "char >> >> >> toString()" living in the root Object. I wish there was an nice, >> >> clean, >> >> >> elegant solution to this ... >> >> > >> >> > I've wondered about that myself, but I guess having toString() >> return >> >> > char[] is >> >> > not so bad. The magic of UTF-8 does, after all, allow us to store >> >> every >> >> > character in a char[] (even though not in a char). >> >> > >> >> > But it would be really, really, /really/ cool, if all string types >> >> would >> >> > *implicitly* cast to one another, *and* go through the relevant >> >> std.utf >> >> > conversion routine to do so. Then classes could implement any of >> the >> >> > following >> >> > at their choice: >> >> > >> >> > # char[] toString(); >> >> > # wchar[] toString(); >> >> > # dchar[] toString(); >> >> > >> >> > Walter has opposed the notion that even /explicit/ casts from >> string >> >> to >> >> > string >> >> > should not do any conversion. I suggest: >> >> >> >> I believe Walters opposition was due to the fact that a conversion > would >> >> create inconsistency between string types and ubyte etc, also that >> the >> >> ability to 'paint' one type as another is desired. >> >> >> >> I think the fact that char, wchar, and dchar have a specified >> encoding >> >> sets them apart from other types, this fact makes painting one string >> >> type >> >> to another completely useless, I cannot think of a reason to paint a >> >> char[], wchar[] or dchar[] to each other? can you? >> >> >> >> If you can then I suggest something like: >> >> >> >> > # c = cast(char[]) cast(void[]) d; // does not call toUTF8() >> >> >> >> will suffice. >> >> >> >> It *does* make sense to paint char[], wchar[] or dchar[] as ubyte[] >> or >> >> void[] etc so what I suggest is that conversion does occur, but, only > if >> >> both the source type and destination type have a specified encoding, >> >> i.e. >> >> char, wchar and dchar to char, wchar or dchar. >> >> >> >> In conclusion I cannot see any valid reason not to make this change, >> I >> >> believe it makes string handling: >> >> - simpler >> >> - more consistent >> >> - less error prone >> >> >> >> This change would make a string class totally useless, which I >> believe >> >> was >> >> Walters original intention when creating these types. >> >> >> >> Regan >> >> >> >> -- >> >> Using M2, Opera's revolutionary e-mail client: >> http://www.opera.com/m2/ >> > >> > >> >> >> >> -- >> Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ > > -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
August 25, 2004 Re: String equivalence (was: the $ token) | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | "Regan Heath" <regan@netwin.co.nz> wrote in message news:opsc9jlr0b5a2sq9@digitalmars.com... > On Tue, 24 Aug 2004 14:58:09 -0700, antiAlias <fu@bar.com> wrote: > > I thought about trying to get around the toString() issue using opCat() > > and > > opCat_r(). It /nearly/ works ... the nice thing about opCat() et. al. is > > that they're not overriding anything (like toString) and therefore can > > have > > pretty much any kind of argument and/or return value. For example: > > > > class A > > { > > dchar[] opCat (dchar[] x) {...} > > > > dchar[] opCat (char[] x) {...} > > > > dchar[] opCat (wchar[] x) {} > > > > dchar[] opCat (int x) {..} > > > > // plus the opCat_r() equivalents > > } > > > > This looked really promising! However, it all fell apart when trying to > > add > > a different return type: > > > > char[] opCat (char[] x) {...} > > > > because D only looks at the method name and argument type, and ignores > > the > > return type. Therefore, a conflict occurs between two operators, and the > > compiler throws an error. Adopting a type promotion approach (as both > > yourself and Matthew have suggested) would probably have to fix this > > bugaboo. > > Yeah.. it would be nice to have the return type included in the method lookup.. it would be breaking from C/C++ convention, apart from that is it really that hard to do? AFAIK, the issue has always been "what happens if the return-value is not assigned? Then you've lost part of the signature, and conflict can arise". This wouldn't occur with opCat() and friends because there's always a left and right operand ... |
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to antiAlias | On Tue, 24 Aug 2004 18:10:53 -0700, antiAlias wrote: > "Regan Heath" <regan@netwin.co.nz> wrote in message news:opsc9jlr0b5a2sq9@digitalmars.com... >> On Tue, 24 Aug 2004 14:58:09 -0700, antiAlias <fu@bar.com> wrote: [snip] >> Yeah.. it would be nice to have the return type included in the method lookup.. it would be breaking from C/C++ convention, apart from that is it really that hard to do? > > AFAIK, the issue has always been "what happens if the return-value is not assigned? Then you've lost part of the signature, and conflict can arise". This wouldn't occur with opCat() and friends because there's always a left and right operand ... In my hypothetically 'good' language, return values would either always be assigned or explicitly rejected. int funcA() { return 0; } float funcA() { return 1.2; } int x; float y; x = funcA(); // Return 0 assigned y = funcA(); // Return 1.2 assigned cast(int)funcA(); // Return 0 rejected. cast(float)funcA(); // Return 1.2 rejected. y = cast(int)funcA(); // Return 0 converted to float and assigned. x = cast(int)(cast(float)funcA()); // Return 1.2 converted to int and assigned. -- Derek Melbourne, Australia 25/Aug/04 11:12:00 AM |
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | Here's some ambiguity with overloading on return type;
# SomeType f1() { return new SomeType; }
# SomeOtherType f1() { return new SomeOtherType; }
# void f2(SomeType t) {
# printf("got SomeType\n");
# }
# void f2(SomeOtherType t) {
# printf("got SomeOtherType\n");
# }
#
# int main() {
# f2(f1);
# return 0;
# }
IMHO, mutually recursive type signatures are a Bad Thing(TM).
Derek Parnell wrote:
> On Tue, 24 Aug 2004 18:10:53 -0700, antiAlias wrote:
>
>
>>"Regan Heath" <regan@netwin.co.nz> wrote in message
>>news:opsc9jlr0b5a2sq9@digitalmars.com...
>>
>>>On Tue, 24 Aug 2004 14:58:09 -0700, antiAlias <fu@bar.com> wrote:
>
>
> [snip]
>
>
>>>Yeah.. it would be nice to have the return type included in the method
>>>lookup.. it would be breaking from C/C++ convention, apart from that is it
>>>really that hard to do?
>>
>>AFAIK, the issue has always been "what happens if the return-value is not
>>assigned? Then you've lost part of the signature, and conflict can arise".
>>This wouldn't occur with opCat() and friends because there's always a left
>>and right operand ...
>
>
> In my hypothetically 'good' language, return values would either always be
> assigned or explicitly rejected.
>
> int funcA() { return 0; }
> float funcA() { return 1.2; }
> int x;
> float y;
>
>
> x = funcA(); // Return 0 assigned
> y = funcA(); // Return 1.2 assigned
> cast(int)funcA(); // Return 0 rejected.
> cast(float)funcA(); // Return 1.2 rejected.
> y = cast(int)funcA(); // Return 0 converted to float and assigned.
> x = cast(int)(cast(float)funcA()); // Return 1.2 converted to int and
> assigned.
>
|
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to Devin Papineau | Right. But that doesn't apply when there's /always/ a left & right operand present (such as with opCat and friends). We're specifically avoiding the general case, such as you illustrated, in an effort to explore how type-promotion + operator-overloading might resolve some thorny issues. No offence intended. "Devin Papineau" <devin_papineau@sympatico.ca> wrote in message news:cggqgv$1hk6$1@digitaldaemon.com... > Here's some ambiguity with overloading on return type; > > # SomeType f1() { return new SomeType; } > # SomeOtherType f1() { return new SomeOtherType; } > # void f2(SomeType t) { > # printf("got SomeType\n"); > # } > # void f2(SomeOtherType t) { > # printf("got SomeOtherType\n"); > # } > # > # int main() { > # f2(f1); > # return 0; > # } > > IMHO, mutually recursive type signatures are a Bad Thing(TM). > > Derek Parnell wrote: > > On Tue, 24 Aug 2004 18:10:53 -0700, antiAlias wrote: > > > > > >>"Regan Heath" <regan@netwin.co.nz> wrote in message news:opsc9jlr0b5a2sq9@digitalmars.com... > >> > >>>On Tue, 24 Aug 2004 14:58:09 -0700, antiAlias <fu@bar.com> wrote: > > > > > > [snip] > > > > > >>>Yeah.. it would be nice to have the return type included in the method lookup.. it would be breaking from C/C++ convention, apart from that is it > >>>really that hard to do? > >> > >>AFAIK, the issue has always been "what happens if the return-value is not > >>assigned? Then you've lost part of the signature, and conflict can arise". > >>This wouldn't occur with opCat() and friends because there's always a left > >>and right operand ... > > > > > > In my hypothetically 'good' language, return values would either always be > > assigned or explicitly rejected. > > > > int funcA() { return 0; } > > float funcA() { return 1.2; } > > int x; > > float y; > > > > > > x = funcA(); // Return 0 assigned > > y = funcA(); // Return 1.2 assigned > > cast(int)funcA(); // Return 0 rejected. > > cast(float)funcA(); // Return 1.2 rejected. > > y = cast(int)funcA(); // Return 0 converted to float and assigned. > > x = cast(int)(cast(float)funcA()); // Return 1.2 converted to int and > > assigned. > > |
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to antiAlias | On Tue, 24 Aug 2004 18:49:44 -0700, antiAlias <fu@bar.com> wrote: > Right. > > But that doesn't apply when there's /always/ a left & right operand present > (such as with opCat and friends). We're specifically avoiding the general > case, such as you illustrated, in an effort to explore how type-promotion + > operator-overloading might resolve some thorny issues. No offence intended. Also, can't we resolve the case below by calling it an error and requiring some guidance from the programmer eg. # int main() { # f2(cast(SomeType)f1()); # return 0; # } to print "got SomeType" # int main() { # f2(cast(SomeOtherType)f1()); # return 0; # } to print "got SomeOtherType" > "Devin Papineau" <devin_papineau@sympatico.ca> wrote in message > news:cggqgv$1hk6$1@digitaldaemon.com... >> Here's some ambiguity with overloading on return type; >> >> # SomeType f1() { return new SomeType; } >> # SomeOtherType f1() { return new SomeOtherType; } >> # void f2(SomeType t) { >> # printf("got SomeType\n"); >> # } >> # void f2(SomeOtherType t) { >> # printf("got SomeOtherType\n"); >> # } >> # >> # int main() { >> # f2(f1); >> # return 0; >> # } >> >> IMHO, mutually recursive type signatures are a Bad Thing(TM). >> >> Derek Parnell wrote: >> > On Tue, 24 Aug 2004 18:10:53 -0700, antiAlias wrote: >> > >> > >> >>"Regan Heath" <regan@netwin.co.nz> wrote in message >> >>news:opsc9jlr0b5a2sq9@digitalmars.com... >> >> >> >>>On Tue, 24 Aug 2004 14:58:09 -0700, antiAlias <fu@bar.com> wrote: >> > >> > >> > [snip] >> > >> > >> >>>Yeah.. it would be nice to have the return type included in the >> method >> >>>lookup.. it would be breaking from C/C++ convention, apart from that >> is > it >> >>>really that hard to do? >> >> >> >>AFAIK, the issue has always been "what happens if the return-value is > not >> >>assigned? Then you've lost part of the signature, and conflict can > arise". >> >>This wouldn't occur with opCat() and friends because there's always a > left >> >>and right operand ... >> > >> > >> > In my hypothetically 'good' language, return values would either >> always > be >> > assigned or explicitly rejected. >> > >> > int funcA() { return 0; } >> > float funcA() { return 1.2; } >> > int x; >> > float y; >> > >> > >> > x = funcA(); // Return 0 assigned >> > y = funcA(); // Return 1.2 assigned >> > cast(int)funcA(); // Return 0 rejected. >> > cast(float)funcA(); // Return 1.2 rejected. >> > y = cast(int)funcA(); // Return 0 converted to float and assigned. >> > x = cast(int)(cast(float)funcA()); // Return 1.2 converted to int >> and >> > assigned. >> > > > -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | On Wed, 25 Aug 2004 11:19:53 +1000, Derek Parnell <derek@psych.ward> wrote: <snip> > In my hypothetically 'good' language, return values would either always be > assigned or explicitly rejected. > > int funcA() { return 0; } > float funcA() { return 1.2; } > int x; > float y; > cast(int)funcA(); // Return 0 rejected. > cast(float)funcA(); // Return 1.2 rejected. Are these backwards? or am I not understanding what you mean when you say: "Return 0 rejected." ?? Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | On Wed, 25 Aug 2004 16:47:10 +1200, Regan Heath wrote: > On Wed, 25 Aug 2004 11:19:53 +1000, Derek Parnell <derek@psych.ward> wrote: <snip> >> In my hypothetically 'good' language, return values would either always >> be >> assigned or explicitly rejected. >> >> int funcA() { return 0; } >> float funcA() { return 1.2; } >> int x; >> float y; > >> cast(int)funcA(); // Return 0 rejected. >> cast(float)funcA(); // Return 1.2 rejected. > > Are these backwards? or am I not understanding what you mean when you say: > "Return 0 rejected." > > ?? The "cast(int)funcA();" is meant to call the function that returns an int. The "cast(float)funcA();" is meant to call the function that returns a float. This is a way of telling the compiler which function I want given that there is no other way to tell. You might like to use ... use(int)funcA(); // Return 0 rejected. use(float)funcA(); // Return 1.2 rejected. instead of 'cast'. -- Derek Melbourne, Australia 25/Aug/04 3:11:24 PM |
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | On Wed, 25 Aug 2004 15:14:08 +1000, Derek Parnell <derek@psych.ward> wrote: > On Wed, 25 Aug 2004 16:47:10 +1200, Regan Heath wrote: > >> On Wed, 25 Aug 2004 11:19:53 +1000, Derek Parnell <derek@psych.ward> wrote: >> <snip> >>> In my hypothetically 'good' language, return values would either always >>> be >>> assigned or explicitly rejected. >>> >>> int funcA() { return 0; } >>> float funcA() { return 1.2; } >>> int x; >>> float y; >> >>> cast(int)funcA(); // Return 0 rejected. >>> cast(float)funcA(); // Return 1.2 rejected. >> >> Are these backwards? or am I not understanding what you mean when you say: >> "Return 0 rejected." >> >> ?? > > The "cast(int)funcA();" is meant to call the function that returns an int. I thought so.. why does the comment say "Return 0 rejected"? > The "cast(float)funcA();" is meant to call the function that returns a > float. > > This is a way of telling the compiler which function I want given that > there is no other way to tell. You might like to use ... > > use(int)funcA(); // Return 0 rejected. > use(float)funcA(); // Return 1.2 rejected. > > instead of 'cast'. Nah, cast works for me. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/ |
August 25, 2004 Re: String equivalence | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | "Regan Heath" <regan@netwin.co.nz> wrote in message news:opsc9v0tvj5a2sq9@digitalmars.com... > On Wed, 25 Aug 2004 15:14:08 +1000, Derek Parnell <derek@psych.ward> wrote: > > On Wed, 25 Aug 2004 16:47:10 +1200, Regan Heath wrote: > > > >> On Wed, 25 Aug 2004 11:19:53 +1000, Derek Parnell <derek@psych.ward> > >> wrote: > >> <snip> > >>> In my hypothetically 'good' language, return values would either always > >>> be > >>> assigned or explicitly rejected. > >>> > >>> int funcA() { return 0; } > >>> float funcA() { return 1.2; } > >>> int x; > >>> float y; > >> > >>> cast(int)funcA(); // Return 0 rejected. > >>> cast(float)funcA(); // Return 1.2 rejected. > >> > >> Are these backwards? or am I not understanding what you mean when you > >> say: > >> "Return 0 rejected." > >> > >> ?? > > > > The "cast(int)funcA();" is meant to call the function that returns an > > int. > > I thought so.. why does the comment say "Return 0 rejected"? > > > The "cast(float)funcA();" is meant to call the function that returns a > > float. > > > > This is a way of telling the compiler which function I want given that there is no other way to tell. You might like to use ... > > > > use(int)funcA(); // Return 0 rejected. > > use(float)funcA(); // Return 1.2 rejected. > > > > instead of 'cast'. > > Nah, cast works for me. Me too. Seems like a perfectly nice, albeit not pretty, iDiom. |
Copyright © 1999-2021 by the D Language Foundation