April 27, 2012
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...
April 27, 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.
>
>
> T


I always thought that D follows the same rules as Java, C++ and C# have. Meaning you can use an instance object to call a static 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


April 27, 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
April 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...
>
> -Steve

Elaborate please how UFCS would help in that context.



April 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:
>
>> With the advent of UFCS, this argument has much less teeth.  Maybe it should be revisited...
>>
>> -Steve
>
> Elaborate please how UFCS would help in that context.

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.

-Steve
April 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:
>
>> 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...
>>>
>>> -Steve
>>
>> Elaborate please how UFCS would help in that context.
>
> 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.

I agree it is ugly. If there is a way out (reason why i asked), we should just dump it.
April 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 should
just 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.


April 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:
>> 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:
>>>
>>>> With the advent of UFCS, this argument has much less teeth.  Maybe it should be revisited...
>>>>
>>>> -Steve
>>>
>>> Elaborate please how UFCS would help in that context.
>>
>> 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.
>
> I agree it is ugly. If there is a way out (reason why i asked), we should just dump it.

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
}

-Steve
April 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:
>>
>> I agree it is ugly. If there is a way out (reason why i asked), we should
> just 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.

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());
}
April 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
> }
>
> -Steve

But 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.
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home