December 30, 2010
> 	?? The only type in this list without a division operator is vector
> all the others have it.

Matrix matrix, matrix vector, vector matrix division also not defined, there is one syntactic similarity but it is not division.
Didn't give much of a thought to others since vector, matrix and scalar operations takes already quite a bit space.

> 	I'm sorry? What do you call the "generic case" here? All this list
> shows is that each operator needs to be implemented individually
> anyway. Andrei's point was exactly the reverse: he claims that most
> operators can be implemented in groups which clearly isn't the case

I don't agree, majority of the cases you duplicate almost all of the code and just change the operator. That was the thing i meant with "generic case".
If i wasn't clear, say:

vector opBinary(string op)(scalar s) if(op == "+" || op == "-" ....) {
	static if(op == "/")
		return general("*")(1/s); // particular case
	else
		return general(op)(s); // general case, just a one-liner mixin
}

vector opBinary(string op)(vector v) if(op == "+" || op == "-" ....) {
	return general(op)(v); // again, just a one-liner mixin
}

Same goes for matrix, particular case being the multiplication.

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
December 30, 2010
On Thu, 30 Dec 2010 17:03:05 -0500, so <so@so.do> wrote:

>> 	?? The only type in this list without a division operator is vector
>> all the others have it.
>
> Matrix matrix, matrix vector, vector matrix division also not defined, there is one syntactic similarity but it is not division.
> Didn't give much of a thought to others since vector, matrix and scalar operations takes already quite a bit space.
>
>> 	I'm sorry? What do you call the "generic case" here? All this list
>> shows is that each operator needs to be implemented individually
>> anyway. Andrei's point was exactly the reverse: he claims that most
>> operators can be implemented in groups which clearly isn't the case
>
> I don't agree, majority of the cases you duplicate almost all of the code and just change the operator. That was the thing i meant with "generic case".
> If i wasn't clear, say:
>
> vector opBinary(string op)(scalar s) if(op == "+" || op == "-" ....) {
> 	static if(op == "/")
> 		return general("*")(1/s); // particular case
> 	else
> 		return general(op)(s); // general case, just a one-liner mixin
> }
>
> vector opBinary(string op)(vector v) if(op == "+" || op == "-" ....) {
> 	return general(op)(v); // again, just a one-liner mixin
> }
>
> Same goes for matrix, particular case being the multiplication.

Actually, that doesn't work currently.  But I think this is a situation that can be fixed.

Essentially, you can't overload templates.  You have to do something like this instead:

vector opBinary(string op, T)(T s) if(is(T == scalar) && (op == "+" || op == "-" ....)) {
	static if(op == "/")
		return general("*")(1/s); // particular case
	else
		return general(op)(s); // general case, just a one-liner mixin
}

vector opBinary(string op, T)(T v) if(is(T == vector) && (op == "+" || op == "-" ....)) {
	return general(op)(v); // again, just a one-liner mixin
}

So, it makes things difficult in this regard too, but I really hope this can be solved.  It's already been stated in TDPL that templates will be able to overload with non-templates.  I think this means they should overload with templates also.

Note that these solutions may look simple and easy to you, but they look convoluted and messy to me ;)

-Steve
December 31, 2010
Michel Fortin <michel.fortin@michelf.com> wrote:


> I stubbled upon this yesterday:
>
> 	Template This Parameters
>
> 	TemplateThisParameters are used in member function templates to pick up the type of the this reference.
> 	import std.stdio;
>
> 	struct S
> 	{
> 		const void foo(this T)(int i)
> 		{
> 			writeln(typeid(T));
> 		}
> 	}
>
> <http://www.digitalmars.com/d/2.0/template.html>
>
> Looks like you could return the type of this this way...

The problem of template this parameters is that it doesn't work as one
might expect:

class A {
    void bar( this T )( ) {
        writeln( typeid( T ) );
    }
}

class B : A {
}

void main( ) {
    A a = new B;
    a.bar();
}

Surely this will print modulename.B, right?

Wrong. It prints modulename.A, as A is the type of the reference
from which the function is called. It looks like a way to automagically
override a function for each subclass, but no.


-- 
Simen
December 31, 2010
On Thu, 30 Dec 2010 19:17:09 +0100, Max Samukha <spambox@d-coding.com> wrote:

> On 12/30/2010 07:08 PM, Steven Schveighoffer wrote:
>
>>
>> auto opAdd(Foo other)
>>
>> vs.
>>
>> auto opBinary(string op)(Foo other) if (op == "+")
>
> For the latter not to look so intimidating, it can be shortened to:
>
> auto opBinary(string op : "+")(Foo other)

Sadly, that shortcut does not allow for grouping. :(

Perhaps we could get a specialization for that, though:

auto opBinary( string op : "+" | "-" )( Foo other )

for instance.

-- 
Simen
December 31, 2010
Steven Schveighoffer <schveiguy@yahoo.com> wrote:

> Where the new scheme wins in brevity (for written code at least, and certainly not simpler to understand) is cases where:
>
> 1. inheritance is not used
> 2. you can consolidate many overloads into one function.

As others have pointed out, this likely accounts for 99% of uses.
The one exception is opCat.

-- 
Simen
December 31, 2010
On 12/31/10, Simen kjaeraas <simen.kjaras@gmail.com> wrote:
>

This will give you both:

class A
{
    void bar(this T) ( )
    {
        writeln(typeid(T));
        writeln(typeid(this));
    }
}

class B : A
{
}

void main( )
{
    A a = new B;
    a.bar();
}
December 31, 2010
Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:

> On 12/31/10, Simen kjaeraas <simen.kjaras@gmail.com> wrote:
>>
>
> This will give you both:
>
> class A
> {
>     void bar(this T) ( )
>     {
>         writeln(typeid(T));
>         writeln(typeid(this));
>     }
> }
>
> class B : A
> {
> }
>
> void main( )
> {
>     A a = new B;
>     a.bar();
> }

Indeed it will. Now, if you look closely, you will see that typeid(T) is A, while typeid(this) is B. Testing further:

class A {
   void baz() {
       writeln(typeid(this));
   }
}
class B : A {
}

void main() {
    A a = new B;
    a.baz(); // prints B.
}

We thus see that the template this parameter has absolutely no value.


-- 
Simen
December 31, 2010
On 12/31/10, Simen kjaeraas <simen.kjaras@gmail.com> wrote:
> We thus see that the template this parameter has absolutely no value.

Oh, you thought the D documentation is describing features *that work*? Ha! Classic mistake.

You see, the D documentation is about showcasing features which don't work, while TDPL is about showcasing features which don't even exist yet.
December 31, 2010
Andrei Alexandrescu wrote:
> And I stand by that claim. One aspect that seems to have been forgotten is that types usually implement either op= in terms of op or vice versa. That savings alone is large.
> 
	This could have been done with a couple of stdlib mixins
"generateOpsFromOpAssign" and "generateOpAssignsFromOp".

		Jerome
-- 
mailto:jeberger@free.fr
http://jeberger.free.fr
Jabber: jeberger@jabber.fr



December 31, 2010
On Thu, 30 Dec 2010 21:14:28 -0500, Simen kjaeraas <simen.kjaras@gmail.com> wrote:

> Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
>
>> On 12/31/10, Simen kjaeraas <simen.kjaras@gmail.com> wrote:
>>>
>>
>> This will give you both:
>>
>> class A
>> {
>>     void bar(this T) ( )
>>     {
>>         writeln(typeid(T));
>>         writeln(typeid(this));
>>     }
>> }
>>
>> class B : A
>> {
>> }
>>
>> void main( )
>> {
>>     A a = new B;
>>     a.bar();
>> }
>
> Indeed it will. Now, if you look closely, you will see that typeid(T) is A, while typeid(this) is B. Testing further:
>
> class A {
>     void baz() {
>         writeln(typeid(this));
>     }
> }
> class B : A {
> }
>
> void main() {
>      A a = new B;
>      a.baz(); // prints B.
> }
>
> We thus see that the template this parameter has absolutely no value.

No, it does have value:

class A
{
   string x;
   T setX(this T, U)(U newx)
   {
      this.x = to!string(newx);
      return cast(T)this;
   }
}

class B : A
{
   int y;
   void setY(int newy)
   {
      this.y = newy;
   }
}


void main()
{
   auto b = new B;
   b.setX(5).setY(6);
}

Hey, look! covariance with templates :)

Now if only templates worked in interfaces...

I also have to write a helper function to eliminate that cast (which does a runtime lookup).

-Steve