digitalmars.D - Static method conflicts with non-static method?
- H. S. Teoh (26/26) Apr 26 2012 Is this a bug? Code:
- Paulo Pinto (12/41) Apr 26 2012 I always thought that D follows the same rules as Java, C++ and
- Steven Schveighoffer (13/36) Apr 27 2012 It's not a bug, it's intended behavior. Static members are accessible v...
- so (3/6) Apr 27 2012 Elaborate please how UFCS would help in that context.
- Steven Schveighoffer (7/13) Apr 27 2012 Hm... thinking about it, UFCS requires passing the instance, while stati...
- so (4/20) Apr 27 2012 I agree it is ugly. If there is a way out (reason why i asked),
- Kevin Cox (6/7) Apr 27 2012 just dump it.
- so (18/30) Apr 27 2012 This one is quite important for templates.
- Steven Schveighoffer (23/43) Apr 27 2012 The idea I came up with in my proposal
- so (6/28) Apr 27 2012 But call site remains unchanged, which was the main reason of
- Steven Schveighoffer (17/47) Apr 27 2012 Huh? The main reason of confusion is that the static method is named in...
- so (12/30) Apr 27 2012 With your proposal you can still do "f.open("world");" and get
- Steven Schveighoffer (12/44) Apr 27 2012 The point is, don't provide the alias. Why would anyone do that in this...
- travert phare.normalesup.org (Christophe) (2/5) Apr 28 2012 +1
- Jacob Carlborg (5/28) Apr 27 2012 It's intended behavior but there's a suggestion to change that:
Is this a bug? Code: import std.stdio; struct S { static int func(int x) { return x+1; } int func(int x) { return x+2; } } void main() { S s; writeln(s.func(1)); } DMD (latest git) output: test.d(10): Error: function test.S.func called with argument types: ((int)) matches both: test.S.func(int x) and: test.S.func(int x) The error message is unhelpful, but basically the complaint is that the static method is conflicting with the non-static method. But I would've thought it is unambiguous; I'd expect that s.func should resolve to the non-static method, and S.func to the static method. After all, no object is needed to invoke the static method, and the static method cannot be invoked without an object. T -- The early bird gets the worm. Moral: ewww...
Apr 26 2012
On Friday, 27 April 2012 at 06:14:13 UTC, H. S. Teoh wrote:Is this a bug? Code: import std.stdio; struct S { static int func(int x) { return x+1; } int func(int x) { return x+2; } } void main() { S s; writeln(s.func(1)); } DMD (latest git) output: test.d(10): Error: function test.S.func called with argument types: ((int)) matches both: test.S.func(int x) and: test.S.func(int x) The error message is unhelpful, but basically the complaint is that the static method is conflicting with the non-static method. But I would've thought it is unambiguous; I'd expect that s.func should resolve to the non-static method, and S.func to the static method. After all, no object is needed to invoke the static method, and the static method cannot be invoked without an object. TI always thought that D follows the same rules as Java, C++ and method, even though it is not needed. As such the call becomes ambiguous, because the compiler won't know what it supposed to call. I tried to look in the language reference, but did not find a clear explanation for this, but I would expect such scenarios to be forbidden. This type of code is a pain to maintain if it is allowed. -- Paulo
Apr 26 2012
On Fri, 27 Apr 2012 01:07:03 -0400, H. S. Teoh <hsteoh quickfur.ath.cx> wrote:Is this a bug? Code: import std.stdio; struct S { static int func(int x) { return x+1; } int func(int x) { return x+2; } } void main() { S s; writeln(s.func(1)); } DMD (latest git) output: test.d(10): Error: function test.S.func called with argument types: ((int)) matches both: test.S.func(int x) and: test.S.func(int x) The error message is unhelpful, but basically the complaint is that the static method is conflicting with the non-static method. But I would've thought it is unambiguous; I'd expect that s.func should resolve to the non-static method, and S.func to the static method. After all, no object is needed to invoke the static method, and the static method cannot be invoked without an object.It's not a bug, it's intended behavior. Static members are accessible via an instance pointer. My personal belief is that it shouldn't be this way, especially since you can make factory static methods that look like they are doing something on an instance. I brought this up a while ago, but since when did anyone listen to me? :) Here is a relevant discussion: http://forum.dlang.org/post/j3fi1u$1uge$1 digitalmars.com One of the counter-arguments from Andrei was that static methods can be used as "methods" on types for generic programming. With the advent of UFCS, this argument has much less teeth. Maybe it should be revisited... -Steve
Apr 27 2012
On Friday, 27 April 2012 at 10:48:29 UTC, Steven Schveighoffer wrote:With the advent of UFCS, this argument has much less teeth. Maybe it should be revisited... -SteveElaborate please how UFCS would help in that context.
Apr 27 2012
On Fri, 27 Apr 2012 07:03:02 -0400, so <so so.so> wrote:On Friday, 27 April 2012 at 10:48:29 UTC, Steven Schveighoffer wrote:Hm... thinking about it, UFCS requires passing the instance, while static methods do not. So it doesn't make as much sense as I thought... I still think static methods should not be callable on instances without opt-in from the aggregate author. The confusion it can cause is not worth the benefits IMO. -SteveWith the advent of UFCS, this argument has much less teeth. Maybe it should be revisited... -SteveElaborate please how UFCS would help in that context.
Apr 27 2012
On Friday, 27 April 2012 at 11:23:39 UTC, Steven Schveighoffer wrote:On Fri, 27 Apr 2012 07:03:02 -0400, so <so so.so> wrote:I agree it is ugly. If there is a way out (reason why i asked), we should just dump it.On Friday, 27 April 2012 at 10:48:29 UTC, Steven Schveighoffer wrote:Hm... thinking about it, UFCS requires passing the instance, while static methods do not. So it doesn't make as much sense as I thought... I still think static methods should not be callable on instances without opt-in from the aggregate author. The confusion it can cause is not worth the benefits IMO.With the advent of UFCS, this argument has much less teeth. Maybe it should be revisited... -SteveElaborate please how UFCS would help in that context.
Apr 27 2012
On Apr 27, 2012 7:34 AM, "so" <so so.so> wrote:I agree it is ugly. If there is a way out (reason why i asked), we shouldjust dump it. I don't like the idea either because it is confusing. The only reason I can imagine is if there was polymorphism on statics which I see as a fairly useless feature. I would be interested to hear of possible use cases though.
Apr 27 2012
On Friday, 27 April 2012 at 11:49:08 UTC, Kevin Cox wrote:On Apr 27, 2012 7:34 AM, "so" <so so.so> wrote:This one is quite important for templates. struct A(T) { static T mini() { return T.min; } static T maxi() { return T.max; } } struct B(T) { T[] v; T mini() { return min(v); } T maxi() { return max(v); } } void test(T)(T a) { writeln("min: ", a.mini()); writeln("max: ", a.maxi()); }I agree it is ugly. If there is a way out (reason why i asked), we shouldjust dump it. I don't like the idea either because it is confusing. The only reason I can imagine is if there was polymorphism on statics which I see as a fairly useless feature. I would be interested to hear of possible use cases though.
Apr 27 2012
On Fri, 27 Apr 2012 07:31:50 -0400, so <so so.so> wrote:On Friday, 27 April 2012 at 11:23:39 UTC, Steven Schveighoffer wrote:The idea I came up with in my proposal (http://d.puremagic.com/issues/show_bug.cgi?id=6579) was to allow aliasing the static method into the instance namespace: struct S1 { static void foo() {} alias S1.foo this.foo; } struct S2 { static void foo() {} } void main() { S1 i1; S2 i2; S1.foo(); // ok i1.foo(); // ok S2.foo(); // ok i2.foo(); // error } -SteveOn Fri, 27 Apr 2012 07:03:02 -0400, so <so so.so> wrote:I agree it is ugly. If there is a way out (reason why i asked), we should just dump it.On Friday, 27 April 2012 at 10:48:29 UTC, Steven Schveighoffer wrote:Hm... thinking about it, UFCS requires passing the instance, while static methods do not. So it doesn't make as much sense as I thought... I still think static methods should not be callable on instances without opt-in from the aggregate author. The confusion it can cause is not worth the benefits IMO.With the advent of UFCS, this argument has much less teeth. Maybe it should be revisited... -SteveElaborate please how UFCS would help in that context.
Apr 27 2012
On Friday, 27 April 2012 at 11:51:40 UTC, Steven Schveighoffer wrote:The idea I came up with in my proposal (http://d.puremagic.com/issues/show_bug.cgi?id=6579) was to allow aliasing the static method into the instance namespace: struct S1 { static void foo() {} alias S1.foo this.foo; } struct S2 { static void foo() {} } void main() { S1 i1; S2 i2; S1.foo(); // ok i1.foo(); // ok S2.foo(); // ok i2.foo(); // error } -SteveBut call site remains unchanged, which was the main reason of confusion. If we expect user to read the function declaration anyway, an extra alias won't do much good or probably complicate it even further.
Apr 27 2012
On Fri, 27 Apr 2012 08:11:48 -0400, so <so so.so> wrote:On Friday, 27 April 2012 at 11:51:40 UTC, Steven Schveighoffer wrote:Huh? The main reason of confusion is that the static method is named in such a way that it looks like an instance method. So we prevent that, unless the author of the class (who is deciding the name of the function) deems it should be called on instances example: struct File { static File open(string name) {...} // factory method this(string name); } File f = File("hello"); f.open("world"); // oops! Just opened file world and threw it away f = File.open("world");// better! I challenge you to name File.open some way where it *wouldn't* be confusing when called on an instance :) -SteveThe idea I came up with in my proposal (http://d.puremagic.com/issues/show_bug.cgi?id=6579) was to allow aliasing the static method into the instance namespace: struct S1 { static void foo() {} alias S1.foo this.foo; } struct S2 { static void foo() {} } void main() { S1 i1; S2 i2; S1.foo(); // ok i1.foo(); // ok S2.foo(); // ok i2.foo(); // error } -SteveBut call site remains unchanged, which was the main reason of confusion. If we expect user to read the function declaration anyway, an extra alias won't do much good or probably complicate it even further.
Apr 27 2012
On Friday, 27 April 2012 at 12:35:53 UTC, Steven Schveighoffer wrote:Huh? The main reason of confusion is that the static method is named in such a way that it looks like an instance method. So we prevent that, unless the author of the class (who is deciding the name of the function) deems it should be called on instances example: struct File { static File open(string name) {...} // factory method this(string name); } File f = File("hello"); f.open("world"); // oops! Just opened file world and threw it away f = File.open("world");// better!With your proposal you can still do "f.open("world");" and get the same result if the author provided alias. You are trying to solve another problem, that the author should better state if this is intended. The problem i see is user assumming author is a smart guy. But at the end he finds out the author is as dumb as himself {he should have RTFM :)}I challenge you to name File.open some way where it *wouldn't* be confusing when called on an instance :) -SteveEasy! Don't call on an instance! openFile() out of the struct. I always add "make_" before any static function, otherwise static methods should be precise as http://forum.dlang.org/post/araqkvvgyspzmdecxqxi forum.dlang.org
Apr 27 2012
On Fri, 27 Apr 2012 09:15:31 -0400, so <so so.so> wrote:On Friday, 27 April 2012 at 12:35:53 UTC, Steven Schveighoffer wrote:The point is, don't provide the alias. Why would anyone do that in this case?Huh? The main reason of confusion is that the static method is named in such a way that it looks like an instance method. So we prevent that, unless the author of the class (who is deciding the name of the function) deems it should be called on instances example: struct File { static File open(string name) {...} // factory method this(string name); } File f = File("hello"); f.open("world"); // oops! Just opened file world and threw it away f = File.open("world");// better!With your proposal you can still do "f.open("world");" and get the same result if the author provided alias.You are trying to solve another problem, that the author should better state if this is intended. The problem i see is user assumming author is a smart guy. But at the end he finds out the author is as dumb as himself {he should have RTFM :)}There is no protection D could ever provide against dumb authors ;) He could have named it "close", or "r72" and the compiler is powerless to prevent this! It's useless to try and prevent such things, D compiler is not a psychologist. The problem I see here is that *smart* authors are inhibited from writing smart code.I like having open inside the struct, just a matter of preference. I think File.open implies better than it returns a File more than openFile. -SteveI challenge you to name File.open some way where it *wouldn't* be confusing when called on an instance :) -SteveEasy! Don't call on an instance! openFile() out of the struct. I always add "make_" before any static function, otherwise static methods should be precise as http://forum.dlang.org/post/araqkvvgyspzmdecxqxi forum.dlang.org
Apr 27 2012
"Steven Schveighoffer" , dans le message (digitalmars.D:165141), aThe idea I came up with in my proposal (http://d.puremagic.com/issues/show_bug.cgi?id=6579) was to allow aliasing the static method into the instance namespace:+1
Apr 28 2012
On 2012-04-27 07:07, H. S. Teoh wrote:Is this a bug? Code: import std.stdio; struct S { static int func(int x) { return x+1; } int func(int x) { return x+2; } } void main() { S s; writeln(s.func(1)); } DMD (latest git) output: test.d(10): Error: function test.S.func called with argument types: ((int)) matches both: test.S.func(int x) and: test.S.func(int x) The error message is unhelpful, but basically the complaint is that the static method is conflicting with the non-static method. But I would've thought it is unambiguous; I'd expect that s.func should resolve to the non-static method, and S.func to the static method. After all, no object is needed to invoke the static method, and the static method cannot be invoked without an object.It's intended behavior but there's a suggestion to change that: http://d.puremagic.com/issues/show_bug.cgi?id=3345 -- /Jacob Carlborg
Apr 27 2012