www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - the $ token

reply h3r3tic <h3r3tic dev.null> writes:
disclaimer: sorry if it has been mentioned before


how about adapting the $ token to convert anything to a string ? like

int foo = 5;
char[] bar = $foo;

// bar == "5"

i dont think this would be a large problem to implement whilst BASIC 
dudes would instantly know it's sth bout strings :] in BASIC you read a$ 
as 'a string'.

that's my vote in the $ war ;]
Aug 19 2004
next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
Sorry mate, but that sounds like a ridiculously cheap waste of an operator that
we may well find use for - e.g.
serialisation, built-in rexex, ... - at a later stage.

What's wrong with have a toString() shim function, defined for objects and for
all built-in types. (In fact don't we
have that already? It's been a while since I've delved into the bowels of
Phobos ...)

"h3r3tic" <h3r3tic dev.null> wrote in message
news:cg41l1$2u3m$1 digitaldaemon.com...
 disclaimer: sorry if it has been mentioned before


 how about adapting the $ token to convert anything to a string ? like

 int foo = 5;
 char[] bar = $foo;

 // bar == "5"

 i dont think this would be a large problem to implement whilst BASIC
 dudes would instantly know it's sth bout strings :] in BASIC you read a$
 as 'a string'.

 that's my vote in the $ war ;]

Aug 19 2004
parent reply h3r3tic <h3r3tic dev.null> writes:
Matthew wrote:
 Sorry mate, but that sounds like a ridiculously cheap waste of an operator
that we may well find use for - e.g.
 serialisation, built-in rexex, ... - at a later stage.

i dunno bout built-in rexex(regexp?) but for serialization ? cmon... i'd rather have a function serialize() and $ for strings instead of toString() for strings and $ for serialization... i mean, how often do you perform each of those ? most ppl probably don't do as much serialization as string conversion. using $ for serialization would be a waste IMHO... could u give some more details about the "rexex" thingie ?
Aug 20 2004
next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cg490p$nk$1 digitaldaemon.com>, h3r3tic says...

could u give some more details about the "rexex" thingie ?

Assuming that "regexp" was intended, there is plenty of information about regular expressions on the web, including this nice one: http://gnosis.cx/publish/programming/regular_expressions.html. Just google "regular expressions" for more. For D, however, I plan something more ambitious in the long term - Unicode Regular Expressions - the definition of which is found in Unicode Technical Standard #18 at http://www.unicode.org/reports/tr18/. (Check it out if interested). However, regular expressions (whether ASCII or Unicode) don't seem to require any special characters outside of a string literal. Sure, '$' means "end of string", but you'd pass the regexp pattern inside a string literal. I don't believe that a change to D lexing involving $ would be a good idea here. But I don't want $ used for toString() either. We've only got a few unused ASCII symbols left, so I think we should save them until something /really/ important crops up. Arcane Jill
Aug 20 2004
next sibling parent Helmut Leitner <helmut.leitner wikiservice.at> writes:
Arcane Jill wrote:
 For D, however, I plan something more ambitious in the long term - Unicode
 Regular Expressions - the definition of which is found in Unicode Technical
 Standard #18 at http://www.unicode.org/reports/tr18/. (Check it out if
 interested).

It would be nice to have general regex pattern search operating on any array. Imagine searching patterns in a chess position array or .... -- Helmut Leitner leitner hls.via.at Graz, Austria www.hls-software.com
Aug 20 2004
prev sibling parent "Walter" <newshound digitalmars.com> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cg4b5r$1o0$1 digitaldaemon.com...
 But I don't want $ used for toString() either. We've only got a few unused

 symbols left, so I think we should save them until something /really/

 crops up.

I'm holding it in reserve for a special purpose. Whenever you use the $ in a D program, you have to send $1 to Digital Mars. I should patent that idea, after all, if Amazon got a patent for clicking a mouse button, why not? <g>
Aug 20 2004
prev sibling parent "Matthew" <admin.hat stlsoft.dot.org> writes:
"h3r3tic" <h3r3tic dev.null> wrote in message
news:cg490p$nk$1 digitaldaemon.com...
 Matthew wrote:
 Sorry mate, but that sounds like a ridiculously cheap waste of an operator
that we may well find use for - e.g.
 serialisation, built-in rexex, ... - at a later stage.

i dunno bout built-in rexex(regexp?) but for serialization ? cmon... i'd rather have a function serialize() and $ for strings instead of toString() for strings and $ for serialization... i mean, how often do you perform each of those ? most ppl probably don't do as much serialization as string conversion. using $ for serialization would be a waste IMHO... could u give some more details about the "rexex" thingie ?

They were both simple "for instance"s thrown up on the spur of the moment. My central point, which I believe suffices, is that conversion to string is ably handled already by toString() functions. (Which are far more readable than a non-C-language-standard operator, as well.)
Aug 20 2004
prev sibling next sibling parent reply _ <__member pathlink.com> writes:
It is a goof idea to make the string conversion a little easyer. For example,
when writing a web application, then one must write a lot of string conversions.


But I must agree also, that every symbol is very valuable.
One option is to make the conversion automatic.
I mean
int foo = 5;
char[] bar = ""~foo;
Because usually it is something like:
return "my granny is "~toString(age)~" old";
it could be just:
return "my granny is "~age~" old";

It is easyer to write, but harder to read and to understand the code.

But it is an idea, isn't it? 


In article <cg41l1$2u3m$1 digitaldaemon.com>, h3r3tic says...
disclaimer: sorry if it has been mentioned before


how about adapting the $ token to convert anything to a string ? like

int foo = 5;
char[] bar = $foo;

// bar == "5"

i dont think this would be a large problem to implement whilst BASIC 
dudes would instantly know it's sth bout strings :] in BASIC you read a$ 
as 'a string'.

that's my vote in the $ war ;]

Aug 20 2004
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
You could swritef(), which would be clear, and would probably be less abusive
to the heap to boot!

"_" <__member pathlink.com> wrote in message
news:cg5425$ds2$1 digitaldaemon.com...
 It is a goof idea to make the string conversion a little easyer. For example,
 when writing a web application, then one must write a lot of string
conversions.


 But I must agree also, that every symbol is very valuable.
 One option is to make the conversion automatic.
 I mean
 int foo = 5;
 char[] bar = ""~foo;
 Because usually it is something like:
 return "my granny is "~toString(age)~" old";
 it could be just:
 return "my granny is "~age~" old";

 It is easyer to write, but harder to read and to understand the code.

 But it is an idea, isn't it?


 In article <cg41l1$2u3m$1 digitaldaemon.com>, h3r3tic says...
disclaimer: sorry if it has been mentioned before


how about adapting the $ token to convert anything to a string ? like

int foo = 5;
char[] bar = $foo;

// bar == "5"

i dont think this would be a large problem to implement whilst BASIC
dudes would instantly know it's sth bout strings :] in BASIC you read a$
as 'a string'.

that's my vote in the $ war ;]


Aug 20 2004
parent reply h3r3tic <h3r3tic dev.null> writes:
Matthew wrote:
 You could swritef(), which would be clear, and would probably be less abusive
to the heap to boot!

but it's still so C-ish. being able to do "foo " ~ 5 ~ whatever ~ " bar" would be a GoodThing for projects like DSP.
Aug 20 2004
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"h3r3tic" <h3r3tic dev.null> wrote in message
news:cg63u0$v8v$1 digitaldaemon.com...
 Matthew wrote:
 You could swritef(), which would be clear, and would probably be less abusive
to the heap to boot!

but it's still so C-ish. being able to do "foo " ~ 5 ~ whatever ~ " bar" would be a GoodThing for projects like DSP.

Ah yes, but I think it's been suggested previously many times that the infix string concatenation operator should automatically call toString() on any of its arguments that are not already strings, prior to concatenation. Hence: Object person = new Person("Walter", "Bright"); long factor = 20; "The IQ of" ~ person ~ " is " ~ factor ~ " times that of mortal man"; would cause the call of std.string.toString(long) and Person.toString(), so we'd get: "The IQ of Walter Bright is 20 times that of mortal man": Although I'm one of those that consistently opposes the overloading of << and >>, this is a different case, since every Object has the facility to toString() itself, and the built-ins are already covered. It wouldn't work for structs, but then that's a good thing anyway. For enums, you would provide a suitable toString() in the same module as the enum, and the compiler would use that. btw, if I'm wrong in saying it's been suggested before, I suggest it now.
Aug 20 2004
parent reply "antiAlias" <fu bar.com> writes:
The problems with that particular approach are twofold:

1) enforcing the binding of Phobos via std.string.toString(). There's a few
issues with doing that, but it's perhaps a matter of personal taste rather
than technicalities such as namespace pollution (which std.* is terribly
good at).

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 ...


"Matthew" <admin.hat stlsoft.dot.org> wrote in message
news:cg65e6$100p$1 digitaldaemon.com...
 "h3r3tic" <h3r3tic dev.null> wrote in message

 Matthew wrote:
 You could swritef(), which would be clear, and would probably be less



 but it's still so C-ish. being able to do  "foo " ~ 5 ~ whatever ~ "
 bar" would be a GoodThing for projects like DSP.

Ah yes, but I think it's been suggested previously many times that the

 automatically call toString() on any of its arguments that are not already

     Object    person  =     new Person("Walter", "Bright");
     long        factor    =    20;

     "The IQ of" ~ person ~ " is " ~ factor ~ " times that of mortal man";

 would cause the call of std.string.toString(long) and Person.toString(),

     "The IQ of Walter Bright is 20 times that of mortal man":

 Although I'm one of those that consistently opposes the overloading of <<

 Object has the facility to toString() itself, and the built-ins are

 then that's a good thing anyway. For enums, you would provide a suitable

 the compiler would use that.

 btw, if I'm wrong in saying it's been suggested before, I suggest it now.

Aug 20 2004
next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"antiAlias" <fu bar.com> wrote in message
news:cg68tk$11on$1 digitaldaemon.com...
 The problems with that particular approach are twofold:

 1) enforcing the binding of Phobos via std.string.toString(). There's a few
 issues with doing that, but it's perhaps a matter of personal taste rather
 than technicalities such as namespace pollution (which std.* is terribly
 good at).

 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 ...

Doh! Yes, silly me and my anglophoneaphiling. I'm sure there's an elegant solution out there worth having though. It'd make things much simpler in many ways. It'd also make D amenable to the Fast String Concatenation technique (which a certain mouthy pommie invented ...).
 "Matthew" <admin.hat stlsoft.dot.org> wrote in message
 news:cg65e6$100p$1 digitaldaemon.com...
 "h3r3tic" <h3r3tic dev.null> wrote in message

 Matthew wrote:
 You could swritef(), which would be clear, and would probably be less



 but it's still so C-ish. being able to do  "foo " ~ 5 ~ whatever ~ "
 bar" would be a GoodThing for projects like DSP.

Ah yes, but I think it's been suggested previously many times that the

 automatically call toString() on any of its arguments that are not already

     Object    person  =     new Person("Walter", "Bright");
     long        factor    =    20;

     "The IQ of" ~ person ~ " is " ~ factor ~ " times that of mortal man";

 would cause the call of std.string.toString(long) and Person.toString(),

     "The IQ of Walter Bright is 20 times that of mortal man":

 Although I'm one of those that consistently opposes the overloading of <<

 Object has the facility to toString() itself, and the built-ins are

 then that's a good thing anyway. For enums, you would provide a suitable

 the compiler would use that.

 btw, if I'm wrong in saying it's been suggested before, I suggest it now.


Aug 20 2004
parent reply "antiAlias" <fu bar.com> writes:
Agreed. I'd really like to see automatic conversion through an operator. The
tricky part is dealing with optional format-specifiers: think of dates, for
example. How does one pass a format-specifier to the opString() method,
while doing this:

Date date = new Date (milliseconds_since_1970);

char[] string = "The date is " ~ date;

And what about floating-point?

Perhaps you have to set the format in advance ?

Java only has one char type, so they can get away with this more easily.
What does C# do?


"Matthew" <admin.hat stlsoft.dot.org> wrote in message
news:cg69c1$120n$1 digitaldaemon.com...
 "antiAlias" <fu bar.com> wrote in message

 The problems with that particular approach are twofold:

 1) enforcing the binding of Phobos via std.string.toString(). There's a


 issues with doing that, but it's perhaps a matter of personal taste


 than technicalities such as namespace pollution (which std.* is terribly
 good at).

 2) more importantly: it doesn't work for unicode strings, because


 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 ...

Doh! Yes, silly me and my anglophoneaphiling. I'm sure there's an elegant solution out there worth having though. It'd

 also make D amenable to the Fast String Concatenation technique (which a

 "Matthew" <admin.hat stlsoft.dot.org> wrote in message
 news:cg65e6$100p$1 digitaldaemon.com...
 "h3r3tic" <h3r3tic dev.null> wrote in message

 Matthew wrote:
 You could swritef(), which would be clear, and would probably be





 abusive to the heap to boot!
 but it's still so C-ish. being able to do  "foo " ~ 5 ~ whatever ~ "
 bar" would be a GoodThing for projects like DSP.

Ah yes, but I think it's been suggested previously many times that the

 automatically call toString() on any of its arguments that are not



 strings, prior to concatenation. Hence:
     Object    person  =     new Person("Walter", "Bright");
     long        factor    =    20;

     "The IQ of" ~ person ~ " is " ~ factor ~ " times that of mortal



 would cause the call of std.string.toString(long) and



 so we'd get:
     "The IQ of Walter Bright is 20 times that of mortal man":

 Although I'm one of those that consistently opposes the overloading of



 and >>, this is a different case, since every
 Object has the facility to toString() itself, and the built-ins are

 then that's a good thing anyway. For enums, you would provide a



 toString() in the same module as the enum, and
 the compiler would use that.

 btw, if I'm wrong in saying it's been suggested before, I suggest it






Aug 20 2004
next sibling parent "Matthew" <admin.hat stlsoft.dot.org> writes:
"antiAlias" <fu bar.com> wrote in message
news:cg6ccg$139m$1 digitaldaemon.com...
 Agreed. I'd really like to see automatic conversion through an operator. The
 tricky part is dealing with optional format-specifiers: think of dates, for
 example. How does one pass a format-specifier to the opString() method,
 while doing this:

 Date date = new Date (milliseconds_since_1970);

 char[] string = "The date is " ~ date;

 And what about floating-point?

 Perhaps you have to set the format in advance ?

No. If people want formatting, they can use sprintf() or swritef(). I only think this is workable if the compiler *only* interprets ~ as a call to toString(), which it will either pick if up from the current module or the module of the convertee type or std.string, in that order. I'll turn into an opponent of this idea if we start to move towards an IOStreams kind of thing, with all that hideous setw() manipulator crap.
 Java only has one char type, so they can get away with this more easily.
 What does C# do?

IIRC, it calls the ToString() method. I think there's also IFormatter stuff, but it's been a long time since I had a play, and even then it wasn't that interesting. ;)
 "Matthew" <admin.hat stlsoft.dot.org> wrote in message
 news:cg69c1$120n$1 digitaldaemon.com...
 "antiAlias" <fu bar.com> wrote in message

 The problems with that particular approach are twofold:

 1) enforcing the binding of Phobos via std.string.toString(). There's a


 issues with doing that, but it's perhaps a matter of personal taste


 than technicalities such as namespace pollution (which std.* is terribly
 good at).

 2) more importantly: it doesn't work for unicode strings, because


 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 ...

Doh! Yes, silly me and my anglophoneaphiling. I'm sure there's an elegant solution out there worth having though. It'd

 also make D amenable to the Fast String Concatenation technique (which a

 "Matthew" <admin.hat stlsoft.dot.org> wrote in message
 news:cg65e6$100p$1 digitaldaemon.com...
 "h3r3tic" <h3r3tic dev.null> wrote in message

 Matthew wrote:
 You could swritef(), which would be clear, and would probably be





 abusive to the heap to boot!
 but it's still so C-ish. being able to do  "foo " ~ 5 ~ whatever ~ "
 bar" would be a GoodThing for projects like DSP.

Ah yes, but I think it's been suggested previously many times that the

 automatically call toString() on any of its arguments that are not



 strings, prior to concatenation. Hence:
     Object    person  =     new Person("Walter", "Bright");
     long        factor    =    20;

     "The IQ of" ~ person ~ " is " ~ factor ~ " times that of mortal



 would cause the call of std.string.toString(long) and



 so we'd get:
     "The IQ of Walter Bright is 20 times that of mortal man":

 Although I'm one of those that consistently opposes the overloading of



 and >>, this is a different case, since every
 Object has the facility to toString() itself, and the built-ins are

 then that's a good thing anyway. For enums, you would provide a



 toString() in the same module as the enum, and
 the compiler would use that.

 btw, if I'm wrong in saying it's been suggested before, I suggest it







Aug 21 2004
prev sibling parent Andy Friesen <andy ikagames.com> writes:
antiAlias wrote:
 Agreed. I'd really like to see automatic conversion through an operator. The
 tricky part is dealing with optional format-specifiers: think of dates, for
 example. How does one pass a format-specifier to the opString() method,
 while doing this:
 
 Date date = new Date (milliseconds_since_1970);
 
 char[] string = "The date is " ~ date;
 
 And what about floating-point?
 
 Perhaps you have to set the format in advance ?
 
 Java only has one char type, so they can get away with this more easily.
 What does C# do?

C# "primitive" types aren't. They still inherit Object. The runtime just optimizes them a bit differently when possible. :) (everything has a ToString method: ints, strings, arrays, even pointers) -- andy
Aug 21 2004
prev sibling next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"antiAlias" <fu bar.com> wrote in message
news:cg68tk$11on$1 digitaldaemon.com...
 The problems with that particular approach are twofold:

 1) enforcing the binding of Phobos via std.string.toString(). There's a few
 issues with doing that, but it's perhaps a matter of personal taste rather
 than technicalities such as namespace pollution (which std.* is terribly
 good at).

 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 ...

Easy(-ish). It takes its lead from the leftmost concatenation thingy. In abscense of a leading string, it assumes char[]. Of course, this still requires use of argument-based string-type deduction, as in char[] toString(int , char[]); dchar[] toString(int, dchar[]); but I reckon that facility is going to be needed anyway.
 "Matthew" <admin.hat stlsoft.dot.org> wrote in message
 news:cg65e6$100p$1 digitaldaemon.com...
 "h3r3tic" <h3r3tic dev.null> wrote in message

 Matthew wrote:
 You could swritef(), which would be clear, and would probably be less



 but it's still so C-ish. being able to do  "foo " ~ 5 ~ whatever ~ "
 bar" would be a GoodThing for projects like DSP.

Ah yes, but I think it's been suggested previously many times that the

 automatically call toString() on any of its arguments that are not already

     Object    person  =     new Person("Walter", "Bright");
     long        factor    =    20;

     "The IQ of" ~ person ~ " is " ~ factor ~ " times that of mortal man";

 would cause the call of std.string.toString(long) and Person.toString(),

     "The IQ of Walter Bright is 20 times that of mortal man":

 Although I'm one of those that consistently opposes the overloading of <<

 Object has the facility to toString() itself, and the built-ins are

 then that's a good thing anyway. For enums, you would provide a suitable

 the compiler would use that.

 btw, if I'm wrong in saying it's been suggested before, I suggest it now.


Aug 20 2004
parent "antiAlias" <fu bar.com> writes:
"Matthew" <admin.hat stlsoft.dot.org> wrote in message
 Of course, this still requires use of argument-based string-type

     char[] toString(int , char[]);
     dchar[] toString(int, dchar[]);

 but I reckon that facility is going to be needed anyway.

What follows is just my opinion, and could be completely misguided: Part of the problem here, as noted earlier, is the covariant return type. To provide what you suggest above, Walter will probably need to hack the method-resolution code to perform a special case. IMO, this is just another stake through the heart of the C++ method resolution approach ... such resolution should use everything about the method signature (including its return type) as part of the matching process. But it doesn't. I'd guess it currently doesn't because it would be possible to get confused over which of two (or more) methods to select when the return value is not used, and where the rest of the signature matches exactly. However; there are ways of making that operate acceptably. I'm not sure that it's such a big issue. Still; I don't see the method-matching algorithm ever changing in D. What's currently there is clearly considered to be the most appropriate approach. Hence, the above will likely never become a reality without introducing more special-cases and more confusion. That's rather unfortunate, IMHO. If D were strongly-typed (as is claimed), said algorithm would be quite different, and would likely lend itself more towards this topic without further confusion. The need for method-aliasing would also go away completely (and would likely satisfy 90% of folks who have an opinion on that subject). That should be reserved for a different topic though. Another way to approach the current subject matter is like so: char[] toString (out dchar[]) and/or char[] toString (out wchar[]) Which produce both outputs at the same time. That's seriously fugly, and as inefficient as one might expect. Please ... let's not do that! "Hackety Hack ~ Don't Look Back"
Aug 21 2004
prev sibling next sibling parent reply Batman <Batman_member pathlink.com> writes:
In article <cg68tk$11on$1 digitaldaemon.com>, antiAlias says...

providing
a "dchar toString()" in each class is not covariant with the "char
toString()" living in the root Object.

What does covariant mean exactly?
Aug 20 2004
parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"Batman" <Batman_member pathlink.com> wrote in message
news:cg6pcs$1cch$1 digitaldaemon.com...
 In article <cg68tk$11on$1 digitaldaemon.com>, antiAlias says...

providing
a "dchar toString()" in each class is not covariant with the "char
toString()" living in the root Object.

What does covariant mean exactly?

Well, I won't profer a definition of the word, but it is usually used in software engineering to describe the following condition class B {} class D : public B {} class X { virtual B clone(); } class Y : public X { virtual D clone(); } Because D is (publicly) derived from B, it is legitimate for Y's overload of X's clone() method to return D instead of B. This is because inheritance is an "Is-A" relationship. Hence, any D is-a B. Since X's clone() requires a B, Y's clone() can return a D, because a D is-a B. Make sense? (I hope so, 'cos that's my top shelf explanation. You'll have to hope for other posts if not. <G>)
Aug 20 2004
parent Matthias Becker <Matthias_member pathlink.com> writes:
"Batman" <Batman_member pathlink.com> wrote in message
news:cg6pcs$1cch$1 digitaldaemon.com...
 In article <cg68tk$11on$1 digitaldaemon.com>, antiAlias says...

providing
a "dchar toString()" in each class is not covariant with the "char
toString()" living in the root Object.

What does covariant mean exactly?


It's just the opposit of contravariant.
Well, I won't profer a definition of the word, but it is usually used in
software engineering to describe the following
condition

class B
{}
class D : public B
{}

class X
{
    virtual B clone();
}

class Y : public X
{
    virtual D clone();
}

Because D is (publicly) derived from B, it is legitimate for Y's overload of
X's clone() method to return D instead of
B.

This is because inheritance is an "Is-A" relationship. Hence, any D is-a B.

Since X's clone() requires a B, Y's clone() can return a D, because a D is-a B.

Make sense? (I hope so, 'cos that's my top shelf explanation. You'll have to
hope for other posts if not. <G>)

Well, in D (and in C++) derived classes are covariant to their base classes in other languages they possibly aren't. Even in D classes aren't covariant to the interfaces they implement. -- Matthias Becker
Aug 22 2004
prev sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
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: # char[] c; # dchar[] d; # # c = d; // calls toUTF8() # c = cast(char[]) d; // calls toUTF8() # c = cast(char[]) cast(void[]) d; // does not call toUTF8() The last case is to cover the unlikely circumstance that you might want to "paint" the { length, address } structure. Obviously, casting from string to non-string or vice-versa should use the paint method as now. The current syntax is confusing. For example: # char[] c; # dchar[] d; # # d = "hello"; // converts # d = cast(dchar[]) "hello"; // converts # # c = "hello"; # d = c; // does not convert # d = cast(dchar[]) c; // does not convert The explanation is that in these cases, toUTFxx() is not called - instead, the conversion happens at compile-time (the string being a compile-time constant). But I would prefer it if strings were much easier to interchange. Maybe there is a need for a String class after all? Something like: # struct String # { # enum { UTF8, UTF16, UTF32 } Encoding; # Encoding encoding; # union # { # char[] c; # wchar[] w; # dchar[] d; # } # /* loads of useful functions */ # } I dunno. Just throwing ideas around. Arcane Jill
Aug 22 2004
next sibling parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <cg9rfu$brl$1 digitaldaemon.com>, Arcane Jill says...

Typo correction:

Walter has opposed the notion that even /explicit/ casts from string to string
should not do any conversion.

should read: "Walter has opposed the notion that even /explicit/ casts from string to string should do any conversion." (I don't normally bother to correct typos, but in this case I didn't want anyone being accidently misrepresented). Jill
Aug 22 2004
prev sibling next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
Hmm. It's always a bit dodgy to have casts do any implicit work, but since
short->double does work, I don't really see
why casting dchar[]->wchar[].

I can't think of any major objection why we shouldn't have it, at least in
explicit form.

"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cg9rfu$brl$1 digitaldaemon.com...
 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: # char[] c; # dchar[] d; # # c = d; // calls toUTF8() # c = cast(char[]) d; // calls toUTF8() # c = cast(char[]) cast(void[]) d; // does not call toUTF8() The last case is to cover the unlikely circumstance that you might want to "paint" the { length, address } structure. Obviously, casting from string to non-string or vice-versa should use the paint method as now. The current syntax is confusing. For example: # char[] c; # dchar[] d; # # d = "hello"; // converts # d = cast(dchar[]) "hello"; // converts # # c = "hello"; # d = c; // does not convert # d = cast(dchar[]) c; // does not convert The explanation is that in these cases, toUTFxx() is not called - instead, the conversion happens at compile-time (the string being a compile-time constant). But I would prefer it if strings were much easier to interchange. Maybe there is a need for a String class after all? Something like: # struct String # { # enum { UTF8, UTF16, UTF32 } Encoding; # Encoding encoding; # union # { # char[] c; # wchar[] w; # dchar[] d; # } # /* loads of useful functions */ # } I dunno. Just throwing ideas around. Arcane Jill

Aug 22 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <cg9u7c$dtp$1 digitaldaemon.com>, Matthew says...

Hmm. It's always a bit dodgy to have casts do any implicit work,

Not "always", but often. The following line of D code has an implicit cast in it: # double x = 42; and I don't actually consider that dodgy at all. What I'm suggesting is similar, because there is no loss of information. But I don't have the answer - I'm only citing the problem. The problem is that Object defines this function: # char[] toString(); That's a problem because an internationalized class like - oh, let's say Name (of a human being) is likely to have an internal representation as a dchar[] - and this is precisely what internationalization writer classes are going to require - a succession of dchars. toString() is called in format() because it's in Object and therefore in everything. The upshot of all this is that to send our Name to a console using transcoding techniques you would have to: (1) have toString() call toUTF8() on the internal dchar[] (2) call toUTF32() to get back the dchars to feed into the writer (3) transcode yet again between the writer and the console It would be nicer if toString() could return /any/ kind of string. Or if toString() returned dchar[] only (but that would break existing code). Or if there were a String class which abstracted away the implementation, and toString() returned that (which would also break existing code). Or if we had member template functions and could define toString!(dchar[])() or something. Like I said, I don't have answers, just concerns. All I know is that forcing everything to go via UTF-8 at every toString() juncture is not the most efficient way of going about things. Arcane Jill
Aug 22 2004
parent reply Matthias Becker <Matthias_member pathlink.com> writes:
Hmm. It's always a bit dodgy to have casts do any implicit work,

Not "always", but often. The following line of D code has an implicit cast in it: # double x = 42; and I don't actually consider that dodgy at all. What I'm suggesting is similar, because there is no loss of information. But I don't have the answer - I'm only citing the problem. The problem is that Object defines this function: # char[] toString(); That's a problem because an internationalized class like - oh, let's say Name (of a human being) is likely to have an internal representation as a dchar[] - and this is precisely what internationalization writer classes are going to require - a succession of dchars. toString() is called in format() because it's in Object and therefore in everything. The upshot of all this is that to send our Name to a console using transcoding techniques you would have to: (1) have toString() call toUTF8() on the internal dchar[] (2) call toUTF32() to get back the dchars to feed into the writer (3) transcode yet again between the writer and the console It would be nicer if toString() could return /any/ kind of string.

happens if you implement some of them but not all? This could be very confusing.
Or if
toString() returned dchar[] only (but that would break existing code).

Yes, but I like this idea more then the previous one.
Or if
there were a String class which abstracted away the implementation, and
toString() returned that (which would also break existing code). 

Many people suggested string classes from time to time, but Walter seems not to like that idea. Well, you would get my vote.
Like I said, I don't have answers, just concerns. All I know is that forcing
everything to go via UTF-8 at every toString() juncture is not the most
efficient way of going about things.

Right. -- Matthias Becker
Aug 22 2004
parent Arcane Jill <Arcane_member pathlink.com> writes:
In article <cgaip0$sqf$1 digitaldaemon.com>, Matthias Becker says...

It would be nicer if toString() could return /any/ kind of string. 


No, no. Object can stay as it is. Subclasses would only define /one/ toString() function. Look at it like this. Right now, the following piece of code: # class A # { # dchar[] toString() # { # return cast(dchar[])"A"; # } # } won't compile. The error is "function toString overrides but is not covariant with toString". But, you see, if they /were/ considered covariant, then it would.
But what
happens if you implement some of them but not all?

If you implemented more than one, it would be a compile error, because you can't overload on return type. If you implemented precisely one, an implicit conversion would happen from the type you actually return to the type expected in the calling expression (which could be no conversion at all). If you implemented no versions, the superclass toString() would be used.
Or if
toString() returned dchar[] only (but that would break existing code).

Yes, but I like this idea more then the previous one.

Me too. But Walter would take some convincing.
Or if
there were a String class which abstracted away the implementation, and
toString() returned that (which would also break existing code). 

Many people suggested string classes from time to time, but Walter seems not to like that idea. Well, you would get my vote.

Sure, but in my view, the problem isn't defining a string class per se, it's that Object.toString() would have to return it. Ergo, it would have to be a Phobos-defined string, and I don't think people would like to be tied to a particular string implementation (unless it was /really/ good). Jill
Aug 22 2004
prev sibling parent reply Regan Heath <regan netwin.co.nz> writes:
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/
Aug 22 2004
parent reply "antiAlias" <fu bar.com> writes:
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? Where automated conversion would really help is in stringizing
(the original topic; I think):

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).

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?


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.



"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/

Aug 22 2004
next sibling parent reply Regan Heath <regan netwin.co.nz> writes:
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, 


 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

 character in a char[] (even though not in a char).

 But it would be really, really, /really/ cool, if all string types 

 *implicitly* cast to one another, *and* go through the relevant 

 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 

 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/
Aug 22 2004
next sibling parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsc5skbhm5a2sq9 digitalmars.com>, Regan Heath says...

So, Matthews idea effects the type promotion system,

Matthew's idea? Matthew said something like: "all implicit conversions are a bit dodgy". The notion of making string types interchangable was in fact...
I had a similar idea, 

..Regan's idea, resuggested by me, Jill, in the response to some comment or other about Object.toString().
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. 

That's the ticket.
This is in essence what 
Matthews idea causes, yes?

My suggestion causes the same sequence of events as Matthews idea.

Then there was h3r3tic's idea: "how about adapting the $ token to convert anything to a string?". I've got confused now about which/whose idea you're now talking about.
 Instead, how about a concat(...) method?


Sure. Let's call it opCat(). And while we're at it, let's give in an operator to overload. :) Jill (agreeing with Regan)
Aug 22 2004
next sibling parent reply "Matthew" <admin.hat stlsoft.dot.org> writes:
"Arcane Jill" <Arcane_member pathlink.com> wrote in message
news:cgc036$1u5u$1 digitaldaemon.com...
 In article <opsc5skbhm5a2sq9 digitalmars.com>, Regan Heath says...

So, Matthews idea effects the type promotion system,

Matthew's idea? Matthew said something like: "all implicit conversions are a bit dodgy". The notion of making string types interchangable was in fact...
I had a similar idea,

..Regan's idea, resuggested by me, Jill, in the response to some comment or other about Object.toString().
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.

That's the ticket.
This is in essence what
Matthews idea causes, yes?

My suggestion causes the same sequence of events as Matthews idea.

Then there was h3r3tic's idea: "how about adapting the $ token to convert anything to a string?". I've got confused now about which/whose idea you're now talking about.
 Instead, how about a concat(...) method?


Sure. Let's call it opCat(). And while we're at it, let's give in an operator to overload. :)

I think he meant my suggestion that sequences of ~ involving non string types should be implicitly translated to calls to ?X?.toString() for object types, and to std.string.toString() for scalar types. (I also suggested that structs do not have automatic conversion, and that's a good thing. Given what we're now realising about the non-orthogonal nature of the struct's intent, that seems more sage now than it did when I suggested it.)
Aug 22 2004
parent Regan Heath <regan netwin.co.nz> writes:
On Mon, 23 Aug 2004 15:52:12 +1000, Matthew <admin.hat stlsoft.dot.org> 
wrote:
 "Arcane Jill" <Arcane_member pathlink.com> wrote in message 
 news:cgc036$1u5u$1 digitaldaemon.com...
 In article <opsc5skbhm5a2sq9 digitalmars.com>, Regan Heath says...

So, Matthews idea effects the type promotion system,

Matthew's idea? Matthew said something like: "all implicit conversions are a bit dodgy". The notion of making string types interchangable was in fact...
I had a similar idea,

..Regan's idea, resuggested by me, Jill, in the response to some comment or other about Object.toString().
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.

That's the ticket.
This is in essence what
Matthews idea causes, yes?

My suggestion causes the same sequence of events as Matthews idea.

Then there was h3r3tic's idea: "how about adapting the $ token to convert anything to a string?". I've got confused now about which/whose idea you're now talking about.
 Instead, how about a concat(...) method?


Sure. Let's call it opCat(). And while we're at it, let's give in an operator to overload. :)

I think he meant my suggestion that sequences of ~ involving non string types should be implicitly translated to calls to ?X?.toString() for object types, and to std.string.toString() for scalar types. (I also suggested that structs do not have automatic conversion, and that's a good thing. Given what we're now realising about the non-orthogonal nature of the struct's intent, that seems more sage now than it did when I suggested it.)

Actually I was referring to this idea... "then Matthew's idea about the type being specified by the left-hand side would probably work." posted by 'antiAlias'. Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 23 2004
prev sibling parent reply Regan Heath <regan netwin.co.nz> writes:
On Mon, 23 Aug 2004 05:41:58 +0000 (UTC), Arcane Jill 
<Arcane_member pathlink.com> wrote:

 In article <opsc5skbhm5a2sq9 digitalmars.com>, Regan Heath says...

 So, Matthews idea effects the type promotion system,

Matthew's idea? Matthew said something like: "all implicit conversions are a bit dodgy". The notion of making string types interchangable was in fact...

No this one .. "then Matthew's idea about the type being specified by the left-hand side would probably work." - antiAlias.
 I had a similar idea,

..Regan's idea, resuggested by me, Jill, in the response to some comment or other about Object.toString().
 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.

That's the ticket.
 This is in essence what
 Matthews idea causes, yes?

 My suggestion causes the same sequence of events as Matthews idea.

Then there was h3r3tic's idea: "how about adapting the $ token to convert anything to a string?". I've got confused now about which/whose idea you're now talking about.

I wasn't even aware of this idea :) I think instead of requiring a token it should automatically call toString for any type it is trying to promote to a string.
 Instead, how about a concat(...) method?


Sure. Let's call it opCat(). And while we're at it, let's give in an operator to overload. :)

Don't we already have an opCat? and if not, why not? Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 23 2004
parent reply Arcane Jill <Arcane_member pathlink.com> writes:
In article <opsc7jczjt5a2sq9 digitalmars.com>, Regan Heath says...

 Instead, how about a concat(...) method?


Sure. Let's call it opCat(). And while we're at it, let's give in an operator to overload. :)

Don't we already have an opCat? and if not, why not?

Of course we do. Regan, one thing you should know about my posts is that anything I mark with a smiley is something said with a sense of humor. (I know some folk like to put <g> at the end of every post, but I don't do that). So if you see a smiley from me, it denotes a joke. Similar can be said for any text sandwiched between pseudo-tags like <sarcasm>...</sarcasm> or <rant>...</rant>. I guess I was just hoping you'd see the joke and laugh, but plain text is maybe too awkward a medium for that kind of thing. Jill
Aug 24 2004
parent Regan Heath <regan netwin.co.nz> writes:
On Tue, 24 Aug 2004 10:44:40 +0000 (UTC), Arcane Jill 
<Arcane_member pathlink.com> wrote:
 In article <opsc7jczjt5a2sq9 digitalmars.com>, Regan Heath says...

 Instead, how about a concat(...) method?


Sure. Let's call it opCat(). And while we're at it, let's give in an operator to overload. :)

Don't we already have an opCat? and if not, why not?

Of course we do. Regan, one thing you should know about my posts is that anything I mark with a smiley is something said with a sense of humor. (I know some folk like to put <g> at the end of every post, but I don't do that). So if you see a smiley from me, it denotes a joke. Similar can be said for any text sandwiched between pseudo-tags like <sarcasm>...</sarcasm> or <rant>...</rant>. I guess I was just hoping you'd see the joke and laugh, but plain text is maybe too awkward a medium for that kind of thing.

Duh.. I'm usually pretty good at picking them up. :) Regan -- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 24 2004
prev sibling parent reply "antiAlias" <fu bar.com> writes:
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.



"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


 special-case, as it is here (e.g. int[] does not does anything fancy


 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


 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,


 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

 character in a char[] (even though not in a char).

 But it would be really, really, /really/ cool, if all string types

 *implicitly* cast to one another, *and* go through the relevant

 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

 string
 should not do any conversion. I suggest:

I believe Walters opposition was due to the fact that a conversion



 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



 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/

Aug 24 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
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 

 you
 can just as easily convert them "manually" using the functions in 

 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 

 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 


 special-case, as it is here (e.g. int[] does not does anything fancy


 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


 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 

 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,


 elegant solution to this ...

I've wondered about that myself, but I guess having toString()



 char[] is
 not so bad. The magic of UTF-8 does, after all, allow us to store

 character in a char[] (even though not in a char).

 But it would be really, really, /really/ cool, if all string types

 *implicitly* cast to one another, *and* go through the relevant

 conversion routine to do so. Then classes could implement any of 



 following
 at their choice:

 #    char[] toString();
 #    wchar[] toString();
 #    dchar[] toString();

 Walter has opposed the notion that even /explicit/ casts from 



 to
 string
 should not do any conversion. I suggest:

I believe Walters opposition was due to the fact that a conversion



 create inconsistency between string types and ubyte etc, also that 


 ability to 'paint' one type as another is desired.

 I think the fact that char, wchar, and dchar have a specified 


 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[]


 void[] etc so what I suggest is that conversion does occur, but, only



 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, 


 believe it makes string handling:
   - simpler
   - more consistent
   - less error prone

 This change would make a string class totally useless, which I 


 was
 Walters original intention when creating these types.

 Regan

 --
 Using M2, Opera's revolutionary e-mail client: 



-- 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/
Aug 24 2004
parent reply "antiAlias" <fu bar.com> writes:
"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 ...
Aug 24 2004
parent reply Derek Parnell <derek psych.ward> writes:
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
Aug 24 2004
next sibling parent reply Devin Papineau <devin_papineau sympatico.ca> writes:
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.

Aug 24 2004
parent reply "antiAlias" <fu bar.com> writes:
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




really that hard to do?

AFAIK, the issue has always been "what happens if the return-value is



assigned? Then you've lost part of the signature, and conflict can



This wouldn't occur with opCat() and friends because there's always a



and right operand ...

In my hypothetically 'good' language, return values would either always


 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.


Aug 24 2004
parent Regan Heath <regan netwin.co.nz> writes:
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 



lookup.. it would be breaking from C/C++ convention, apart from that 




really that hard to do?

AFAIK, the issue has always been "what happens if the return-value is



assigned? Then you've lost part of the signature, and conflict can



This wouldn't occur with opCat() and friends because there's always a



and right operand ...

In my hypothetically 'good' language, return values would either


 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 

 assigned.



-- Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
Aug 24 2004
prev sibling parent reply Regan Heath <regan netwin.co.nz> writes:
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/
Aug 24 2004
parent reply Derek Parnell <derek psych.ward> writes:
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
Aug 24 2004
parent reply Regan Heath <regan netwin.co.nz> writes:
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/
Aug 24 2004
next sibling parent "Matthew" <admin stlsoft.dot.dot.dot.dot.org> writes:
"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.
Aug 24 2004
prev sibling parent Derek Parnell <derek psych.ward> writes:
On Wed, 25 Aug 2004 17:25:31 +1200, Regan Heath wrote:

 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"?

Yeah, I suppose 'rejected' is a bit harsh. More like, "The returned value 0 is not assigned to anything, so ignore it".
 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.

But its not likely this will ever make it into D anyhow. ;-) -- Derek Melbourne, Australia 25/Aug/04 5:16:32 PM
Aug 25 2004
prev sibling parent reply "antiAlias" <fu bar.com> writes:
Thinking about this some more, I have a feeling that D would solve a few
problems if it were to support methods for the basic data types:

uint.toString()
uint.opCat()
uint.whatever()

char[].toString()
char[].opCat()
char[].whatever()

dchar[].opCat()
...

Think of them like properties. The useful thing about such things is that
they are overloadable. Thus a char[] might have:

opCat(dchar[])
opCat(int)
opCat(float)
...

and so on. An example implementation for char[] might be thus:

char[] opCat(int x)
{
    return toString() ~ x.toString();
}

char[] opCat (dchar[] x)
{
    return toString() ~ utf.toUtf8(x);
}

On the face of it, this would solve several problems:

1) easy, natural conversion of any data-type to char[] and dchar[]
2) concatenation of arbitrary data types is supported
3) conversion between char[], wchar[], and dchar[] can be performed by
specialized operators

The expression

return "my granny is "~age~" old";

would then be almost trivial for the compiler to support. Appending a class
instance would utilize opCat_r() in the normal fashion. Of course, there's a
problem with what the return value should be for uint.toString() ... char[]?
wchar[]? dchar[]? There's bound to be a good way to resolve that ... or
perhaps there is no type.toString(), and the conversion is performed
explicitly by others?

(for char[])
char[] opCat(int x)
{
    return this ~ string.toString(x);
}

(for dchar[])
dchar[] opCat(int x)
{
    return this ~ string.toWideString(x);
}


Wasn't there another thread (ages ago) that mentioned something like this?




"antiAlias" <fu bar.com> wrote in message
news:cgba37$1e13$1 digitaldaemon.com...
 Right. But I don't think this stuff should be done by a cast(). I mean,

 can just as easily convert them "manually" using the functions in utf.d,
 can't you? Where automated conversion would really help is in stringizing
 (the original topic; I think):

 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

 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).

 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?


 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.



 "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,




 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



 character in a char[] (even though not in a char).

 But it would be really, really, /really/ cool, if all string types



 *implicitly* cast to one another, *and* go through the relevant



 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



 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


 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,


 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


 Walters original intention when creating these types.

 Regan

 --
 Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/


Aug 22 2004
parent Andy Friesen <andy ikagames.com> writes:
antiAlias wrote:
 Thinking about this some more, I have a feeling that D would solve a few
 problems if it were to support methods for the basic data types:
 
 uint.toString()
 uint.opCat()
 uint.whatever()
 
 char[].toString()
 char[].opCat()
 char[].whatever()
 
 dchar[].opCat()
 ...
 
 Think of them like properties. The useful thing about such things is that
 they are overloadable. Thus a char[] might have:
 
 opCat(dchar[])
 opCat(int)
 opCat(float)
 ...
 
 and so on. An example implementation for char[] might be thus:
 
 char[] opCat(int x)
 {
     return toString() ~ x.toString();
 }
 
 char[] opCat (dchar[] x)
 {
     return toString() ~ utf.toUtf8(x);
 }
 
 On the face of it, this would solve several problems:
 
 1) easy, natural conversion of any data-type to char[] and dchar[]
 2) concatenation of arbitrary data types is supported
 3) conversion between char[], wchar[], and dchar[] can be performed by
 specialized operators
 
 The expression
 
 return "my granny is "~age~" old";
 
 would then be almost trivial for the compiler to support. Appending a class
 instance would utilize opCat_r() in the normal fashion. Of course, there's a
 problem with what the return value should be for uint.toString() ... char[]?
 wchar[]? dchar[]? There's bound to be a good way to resolve that ... or
 perhaps there is no type.toString(), and the conversion is performed
 explicitly by others?

I think, if D is going to go this route, it may as well make primitive types into full-blown structs. They could even be defined in Phobos. (through some sort of name-mangling scheme. Maybe extend the language so that keyword is taken to be an identifier) Primitive types in C# are handled this way, and it's pretty cool. The "built-in" types are basically value-classes to which which special-case optimizations are applied. -- andy
Aug 22 2004
prev sibling parent Andy Friesen <andy ikagames.com> writes:
h3r3tic wrote:

 disclaimer: sorry if it has been mentioned before
 
 
 how about adapting the $ token to convert anything to a string ? like
 
 int foo = 5;
 char[] bar = $foo;
 
 // bar == "5"
 
 i dont think this would be a large problem to implement whilst BASIC 
 dudes would instantly know it's sth bout strings :] in BASIC you read a$ 
 as 'a string'.
 
 that's my vote in the $ war ;]

I think $ should be left unused. Metaprogramming tools like Lex, Yacc, SWIG, and ANTLR frequently receive code snippets which are injected into their output. They give special meaning to $ because C doesn't. Assigning meaning to $ would make using these tools in conjunction with D more cumbersome. -- andy
Aug 20 2004