digitalmars.D - Proposal: overload conflict resolution
- Chris Miller (49/49) Dec 10 2006 Given the following function prototypes:
- Kristian Kilpi (5/15) Dec 10 2006 [snip]
- Frits van Bommel (9/29) Dec 10 2006 I like the basic idea, but maybe it gets a bit to hairy when multiple
- Frank Benoit (keinfarbton) (1/3) Dec 10 2006 This gets my vote
- Lars Ivar Igesund (6/11) Dec 10 2006 Yes, this might work.
- Rioshin an'Harthen (7/19) Dec 10 2006 So, we'd have something like
- Frits van Bommel (15/37) Dec 10 2006 I see no reason why you can't declare multiple 'default's, as long as
- Karen Lanrap (7/8) Dec 10 2006 How to make that sure in a sufficiently large coder team?
- Chris Miller (7/33) Dec 10 2006 I thought of it and generally agree it reduces complexity, but doesn't
- Frits van Bommel (7/20) Dec 10 2006 My version allows numbers and strings, as long as only one 'default' is
- Alexander Panek (12/79) Dec 10 2006 As I've already mentioned in #d, I /actually/ like it how it works now
- Chris Nicholson-Sauls (9/76) Dec 11 2006 Personally I just don't think I'd ever have a use for it... Rare is the...
- Pragma (10/90) Dec 11 2006 The Mango example is actually a perfect case for how this can trip
- Derek Parnell (21/30) Dec 11 2006 Would it be possible for the compiler to encode an unqualified string
Given the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types. Proposal: void foo(default char[] s); void foo(wchar[] s); void foo(dchar[] s); foo("hello") will now select the char[] version because it was marked as the default type in the overload. What it does not do: 1) Resolve conflicts between different scopes. 2) Override exact matches. The way overloads work now is helpful in some cases, but in other cases, it's perfectly fine to prefer an overload over another. Example where you do not want a default overload: working with binary, e.g. writing to Stream or Socket, where the wrong type can screw up the format or transmission. Example where you do: custom string object's constructor that wants to allow char[], wchar[] and dchar[] types, but wants to default string literals to char[]. The compiler would go down the line of parameters of overloads, and upon any conflicts, would look for default to resolve them. If default is used to resolve conflicts in more that one of the functions, it's an actual conflict. Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x); Note: this example probably wouldn't actually be used; as with most language constructs, there's a way to abuse it, but this example gets a point across that it at least has logic: bar("hello", 42) chooses the first one because the string literal conflicted and went with the default one. bar("hello"c, 42) chooses the second one; the string literal specified char[] (with the c) and then had a conflict with the second parameter, where default resolved it. The programmer knows which overloads, if any, can be preferred over others, because this feature works only confined within one scope, and so it is safe to let him choose for you. Where this can be useful: 1) String literals conflicting with char[], wchar[] and dchar[]. 2) null conflicting with string types, delegates, pointers, and class references. 3) Integer literals conflicting with the number types. 4) Different levels of derived classes conflicting with each other. Thanks, - Chris
Dec 10 2006
On Sun, 10 Dec 2006 16:36:51 +0200, Chris Miller <chris dprogramming.com> wrote:Given the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types. Proposal: void foo(default char[] s); void foo(wchar[] s); void foo(dchar[] s);[snip] I have hoped that something like this would be possible in C++, and now, in D. Gets my vote!
Dec 10 2006
Chris Miller wrote:Given the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types. Proposal: void foo(default char[] s); void foo(wchar[] s); void foo(dchar[] s);<snip>The compiler would go down the line of parameters of overloads, and upon any conflicts, would look for default to resolve them. If default is used to resolve conflicts in more that one of the functions, it's an actual conflict. Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x);I like the basic idea, but maybe it gets a bit to hairy when multiple parameters can have this attribute... Maybe it should be an attribute of the function instead? Then it becomes quite clear, I think: if there are multiple equally-good matches and among them the number of overloads with the attribute is anything other than one (that is, none or at least two) it's still an error, otherwise the one declared 'default' is picked.
Dec 10 2006
Maybe it should be an attribute of the function instead?This gets my vote
Dec 10 2006
Frank Benoit (keinfarbton) wrote:Yes, this might work. -- Lars Ivar Igesund blog at http://larsivi.net DSource & #D: larsiviMaybe it should be an attribute of the function instead?This gets my vote
Dec 10 2006
"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> wrote:Chris Miller wrote:So, we'd have something like default void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); with only one function of the same name at most with default... I like this :). Votes++ for this modification.Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x);I like the basic idea, but maybe it gets a bit to hairy when multiple parameters can have this attribute... Maybe it should be an attribute of the function instead? Then it becomes quite clear, I think: if there are multiple equally-good matches and among them the number of overloads with the attribute is anything other than one (that is, none or at least two) it's still an error, otherwise the one declared 'default' is picked.
Dec 10 2006
Rioshin an'Harthen wrote:"Frits van Bommel" <fvbommel REMwOVExCAPSs.nl> wrote:I see no reason why you can't declare multiple 'default's, as long as you make sure they don't conflict. Basically, only one would be allowed in the overload set without it being an error. For instance: /// UTF conversion default char[] toString(char[]); char[] toString(wchar[]); /// ditto char[] toString(wchar[]); /// ditto /// Converts a number to a printable representation default char[] toString(int); char[] toString(uint); /// ditto I don't think these will conflict. Now, which one of the latter two to make the default, that's another question... (I just arbitrarily picked one)Chris Miller wrote:So, we'd have something like default void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); with only one function of the same name at most with default...Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x);I like the basic idea, but maybe it gets a bit to hairy when multiple parameters can have this attribute... Maybe it should be an attribute of the function instead? Then it becomes quite clear, I think: if there are multiple equally-good matches and among them the number of overloads with the attribute is anything other than one (that is, none or at least two) it's still an error, otherwise the one declared 'default' is picked.I like this :). Votes++ for this modification.
Dec 10 2006
Frits van Bommel wrote:as long as you make sure they don't conflict.How to make that sure in a sufficiently large coder team? How to find in case of conflicting defaulted overloads the right one in a long chain of derivings. How to find the usages of such defaulted overloads if there is a need to change the default, for example when a library from a different vendor must be used?
Dec 10 2006
On Sun, 10 Dec 2006 11:58:35 -0500, Frits van Bommel <fvbommel REMwOVExCAPSs.nl> wrote:Chris Miller wrote:I thought of it and generally agree it reduces complexity, but doesn't give as much control. Consider one name that has overloads with many different types, like toString; it has conflicts with numbers, strings, and whatever else. Also consider when more than one parameter is involved. I'm not sure which is the better tradeoff.Given the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types. Proposal: void foo(default char[] s); void foo(wchar[] s); void foo(dchar[] s);<snip>The compiler would go down the line of parameters of overloads, and upon any conflicts, would look for default to resolve them. If default is used to resolve conflicts in more that one of the functions, it's an actual conflict. Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x);I like the basic idea, but maybe it gets a bit to hairy when multiple parameters can have this attribute... Maybe it should be an attribute of the function instead? Then it becomes quite clear, I think: if there are multiple equally-good matches and among them the number of overloads with the attribute is anything other than one (that is, none or at least two) it's still an error, otherwise the one declared 'default' is picked.
Dec 10 2006
Chris Miller wrote:On Sun, 10 Dec 2006 11:58:35 -0500, Frits van Bommel <fvbommel REMwOVExCAPSs.nl> wrote:My version allows numbers and strings, as long as only one 'default' is in the overload set. Numbers and strings will never conflict, AFAIK. When it comes to multiple parameters, what kind of use case did you have in mind? I can't think of any at the moment, but that may just be my lack of imagination playing up again :).Maybe it should be an attribute of the function instead? Then it becomes quite clear, I think: if there are multiple equally-good matches and among them the number of overloads with the attribute is anything other than one (that is, none or at least two) it's still an error, otherwise the one declared 'default' is picked.I thought of it and generally agree it reduces complexity, but doesn't give as much control. Consider one name that has overloads with many different types, like toString; it has conflicts with numbers, strings, and whatever else. Also consider when more than one parameter is involved. I'm not sure which is the better tradeoff.
Dec 10 2006
As I've already mentioned in #d, I /actually/ like it how it works now (explicit usage; e.g. you have to append c/w/d each time you pass a string literal). This concept is still the way to go, IMHO, though as D is a language inventing/implementing so much nice paradigms already, this one should have a go, too. It's basically syntactic sugar, but also adds the capability to 'control' usage of functions, which is a good thing. Long story short: Has my vote. :P Kind regards, Alex Chris Miller wrote:Given the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types. Proposal: void foo(default char[] s); void foo(wchar[] s); void foo(dchar[] s); foo("hello") will now select the char[] version because it was marked as the default type in the overload. What it does not do: 1) Resolve conflicts between different scopes. 2) Override exact matches. The way overloads work now is helpful in some cases, but in other cases, it's perfectly fine to prefer an overload over another. Example where you do not want a default overload: working with binary, e.g. writing to Stream or Socket, where the wrong type can screw up the format or transmission. Example where you do: custom string object's constructor that wants to allow char[], wchar[] and dchar[] types, but wants to default string literals to char[]. The compiler would go down the line of parameters of overloads, and upon any conflicts, would look for default to resolve them. If default is used to resolve conflicts in more that one of the functions, it's an actual conflict. Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x); Note: this example probably wouldn't actually be used; as with most language constructs, there's a way to abuse it, but this example gets a point across that it at least has logic: bar("hello", 42) chooses the first one because the string literal conflicted and went with the default one. bar("hello"c, 42) chooses the second one; the string literal specified char[] (with the c) and then had a conflict with the second parameter, where default resolved it. The programmer knows which overloads, if any, can be preferred over others, because this feature works only confined within one scope, and so it is safe to let him choose for you. Where this can be useful: 1) String literals conflicting with char[], wchar[] and dchar[]. 2) null conflicting with string types, delegates, pointers, and class references. 3) Integer literals conflicting with the number types. 4) Different levels of derived classes conflicting with each other. Thanks, - Chris
Dec 10 2006
Chris Miller wrote:Given the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types. Proposal: void foo(default char[] s); void foo(wchar[] s); void foo(dchar[] s); foo("hello") will now select the char[] version because it was marked as the default type in the overload. What it does not do: 1) Resolve conflicts between different scopes. 2) Override exact matches. The way overloads work now is helpful in some cases, but in other cases, it's perfectly fine to prefer an overload over another. Example where you do not want a default overload: working with binary, e.g. writing to Stream or Socket, where the wrong type can screw up the format or transmission. Example where you do: custom string object's constructor that wants to allow char[], wchar[] and dchar[] types, but wants to default string literals to char[]. The compiler would go down the line of parameters of overloads, and upon any conflicts, would look for default to resolve them. If default is used to resolve conflicts in more that one of the functions, it's an actual conflict. Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x); Note: this example probably wouldn't actually be used; as with most language constructs, there's a way to abuse it, but this example gets a point across that it at least has logic: bar("hello", 42) chooses the first one because the string literal conflicted and went with the default one. bar("hello"c, 42) chooses the second one; the string literal specified char[] (with the c) and then had a conflict with the second parameter, where default resolved it. The programmer knows which overloads, if any, can be preferred over others, because this feature works only confined within one scope, and so it is safe to let him choose for you. Where this can be useful: 1) String literals conflicting with char[], wchar[] and dchar[]. 2) null conflicting with string types, delegates, pointers, and class references. 3) Integer literals conflicting with the number types. 4) Different levels of derived classes conflicting with each other. Thanks, - ChrisPersonally I just don't think I'd ever have a use for it... Rare is the string literal in my code without a c|w|d suffix. (Partially because I use Mango an awful lot, which does have a few cases of this ambiguity -- Stdout anyone? But no problem... I never code Stdout("Hello!") but always Stdout("Hello!"c) instead... tada, problem solved with existing features. But apparently a lot of people do see something useful about this. So I abstain and vote neutral. :) -- Chris Nicholson-Sauls
Dec 11 2006
Chris Nicholson-Sauls wrote:Chris Miller wrote:The Mango example is actually a perfect case for how this can trip programmers up. But you're right, using existing features (as minimally intrusive as c/d/w) are the right way to go. Still, I've often wondered if there wasn't a better way. Something like auto defining char data as UTF-8/16/32 based on the *source file encoding* might go a long way to make this a little more implicit. However, I'm not sure if that would be too subtle to maintain practically. -- - EricAnderton at yahooGiven the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types. Proposal: void foo(default char[] s); void foo(wchar[] s); void foo(dchar[] s); foo("hello") will now select the char[] version because it was marked as the default type in the overload. What it does not do: 1) Resolve conflicts between different scopes. 2) Override exact matches. The way overloads work now is helpful in some cases, but in other cases, it's perfectly fine to prefer an overload over another. Example where you do not want a default overload: working with binary, e.g. writing to Stream or Socket, where the wrong type can screw up the format or transmission. Example where you do: custom string object's constructor that wants to allow char[], wchar[] and dchar[] types, but wants to default string literals to char[]. The compiler would go down the line of parameters of overloads, and upon any conflicts, would look for default to resolve them. If default is used to resolve conflicts in more that one of the functions, it's an actual conflict. Strange example: void bar(default char[] s, int x); void bar(char[] s, default long x); Note: this example probably wouldn't actually be used; as with most language constructs, there's a way to abuse it, but this example gets a point across that it at least has logic: bar("hello", 42) chooses the first one because the string literal conflicted and went with the default one. bar("hello"c, 42) chooses the second one; the string literal specified char[] (with the c) and then had a conflict with the second parameter, where default resolved it. The programmer knows which overloads, if any, can be preferred over others, because this feature works only confined within one scope, and so it is safe to let him choose for you. Where this can be useful: 1) String literals conflicting with char[], wchar[] and dchar[]. 2) null conflicting with string types, delegates, pointers, and class references. 3) Integer literals conflicting with the number types. 4) Different levels of derived classes conflicting with each other. Thanks, - ChrisPersonally I just don't think I'd ever have a use for it... Rare is the string literal in my code without a c|w|d suffix. (Partially because I use Mango an awful lot, which does have a few cases of this ambiguity -- Stdout anyone? But no problem... I never code Stdout("Hello!") but always Stdout("Hello!"c) instead... tada, problem solved with existing features. But apparently a lot of people do see something useful about this. So I abstain and vote neutral. :) -- Chris Nicholson-Sauls
Dec 11 2006
On Mon, 11 Dec 2006 16:07:39 -0500, Pragma wrote:...Chris Miller wrote:Given the following function prototypes: void foo(char[] s); void foo(wchar[] s); void foo(dchar[] s); Currently, if you try to do foo("hello"), the compiler will complain because string literals simulteneous match all the above types.Still, I've often wondered if there wasn't a better way.Would it be possible for the compiler to encode an unqualified string literal based on a hierarchy of matches. In other words, if there exists a char[] match use that, otherwise if there exists a wchar[] match then use that, otherwise if there exists a dchar[] match use that else there is no match. In Chris' original example the 'foo(char[])' would match and so the compiler encodes the literal as utf-8. Thus is multiple matches are possible, the compiler chooses them in order of utf-8, utf-16, and utf-32. Thus if the coder explicitly wants a specific 'foo' to be called they would need to explicitly encode the literal with the c/w/d qualifier. This idea seems reasonable and maybe also can be extended in concept to unqualified numeric literals. -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 12/12/2006 9:19:36 AM
Dec 11 2006