Re: overload binary + operator to work with different types

2018-03-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 3/13/18 3:28 PM, Simen Kjærås wrote:

Now, since we've established that there's no way to do exactly what you 
want, maybe it's time to take a look at what you actually want. :p Why 
do you want to write that code? Why would a.append(1, 2, 3); not be good 
enough?


Typically, we can do this with arrays quite easily, especially strings:

arr ~= [1, 2, 3];
str ~= "123";

It would be nice to have another way to do this. a.append(1, 2, 3) would 
work , and you can do it in a nice variadic way with:


append(T[] vals...)

And this won't allocate anything on the heap (this is essentially how I 
did it in dcollections, see 
https://github.com/schveiguy/dcollections/blob/master/dcollections/model/Addable.d#L55).


But most D containers, you would expect to be able to append a range. 
This is what I would recommend. It will work for arrays as well.


-Steve


Re: overload binary + operator to work with different types

2018-03-13 Thread Simen Kjærås via Digitalmars-d-learn

On Tuesday, 13 March 2018 at 18:55:35 UTC, Marc wrote:

I want to basically make this work:


auto l = new List();
l += 5;


I managed to do this:


class List
{
int[] items;
ref List opBinary(string op)(int rhs) if(op == "+")
{
items ~= rhs;
return *this;
}

}

Note the ref in the fucntion return, I also want to return a 
reference to the class so that this Works:



l += 5 + 8 + 9 ... ;


Could someone point out how do that/what's wrong with my 
attempy?


First, D has a concatenation operator (~). Use it instead of + if 
concatenation is what you want.


Now, to your question: classes are reference types in D, so you 
don't need a 'ref' on function:


List opBinary(string op : "~")(int rhs) {
items ~= rhs;
return this;
}

This will return the exact same List that you've just appended 
to. However, that won't do what you're asking, since you 
specifically asked for += (which I will interpret as ~=, for 
reasons explained above). When the operation you want to overload 
is an assignment operator, as in +=, -=, ~=, etc, you'll need to 
write a function called opOpAssign:


List opOpAssign(string op : "~")(int rhs) {
items ~= rhs;
return this;
}

With opOpAssign, this code will work:

unittest {
List a = new List();
a ~= 1;
a ~= 2;
a ~= 3;
}

However, we still haven't gotten code on the format 'a ~= 1 ~ 2 ~ 
3;' to work, and that's because we can't. When you have an 
assignment expression (something that looks like 'lhs = rhs'), 
the left-hand side is evaluated separately from the right-hand 
side, and then the assignment is performed. Since '1 ~ 2 ~ 3' 
doesn't do what you want it to, neither will 'a ~= 1 ~ 2 ~ 3', 
since it's essentially '(a) = (1 ~ 2 ~ 3);'.


Overloading just opBinary though (as in my first example), we can 
make this work: 'a ~ 1 ~ 2 ~ 3;'. The problem, as you probably 
notice, is that there's no assignment there. It looks as though 
you're just concatenating a bunch of items, and then discarding 
the result.


Now, since we've established that there's no way to do exactly 
what you want, maybe it's time to take a look at what you 
actually want. :p Why do you want to write that code? Why would 
a.append(1, 2, 3); not be good enough?


And given that seasoned D veterans know that the lhs and rhs of 
an assignment are evaluated separately, and that 'a ~ b' 
generally doesn't have side effects, you should think very 
carefully through your reasoning for breaking that intuition.


--
  Simen


Re: overload binary + operator to work with different types

2018-03-13 Thread Marc via Digitalmars-d-learn

On Tuesday, 13 March 2018 at 19:05:00 UTC, Jonathan M Davis wrote:
On Tuesday, March 13, 2018 18:55:35 Marc via 
Digitalmars-d-learn wrote:

I want to basically make this work:
>[...]

I managed to do this:
> [...]

}

Note the ref in the fucntion return, I also want to return a

reference to the class so that this Works:
> [...]

Could someone point out how do that/what's wrong with my 
attempy?


+ is overloaded with opBinary, and += is overloaded using 
opOpAssign:


https://dlang.org/spec/operatoroverloading.html#op-assign 
http://ddili.org/ders/d.en/operator_overloading.html


- Jonathan M Davis


Soon as I posted I found out opOpAssign.
I've had got close than I thought:


List opOpAssign(string op)(int rhs) if(op == "+")
{
items ~= rhs;
return this;
}


Thanks!


Re: overload binary + operator to work with different types

2018-03-13 Thread Jonathan M Davis via Digitalmars-d-learn
On Tuesday, March 13, 2018 18:55:35 Marc via Digitalmars-d-learn wrote:
> I want to basically make this work:
> >auto l = new List();
> >l += 5;
>
> I managed to do this:
> >class List
> >{
> >
> > int[] items;
> > ref List opBinary(string op)(int rhs) if(op == "+")
> > {
> >
> > items ~= rhs;
> > return *this;
> >
> > }
>
> }
>
> Note the ref in the fucntion return, I also want to return a
>
> reference to the class so that this Works:
> > l += 5 + 8 + 9 ... ;
>
> Could someone point out how do that/what's wrong with my attempy?

+ is overloaded with opBinary, and += is overloaded using opOpAssign:

https://dlang.org/spec/operatoroverloading.html#op-assign
http://ddili.org/ders/d.en/operator_overloading.html

- Jonathan M Davis