Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 09, 2007 opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
On writing the implementation of a map, where the Valuetype is a set, I had to stop on recognizing, that only opIndexAssign is permitted. I.e.: map[ key]+= element; has no possible overload. OpIndex delivers an rvalue and the only possibility to get an lvalue is in conjunction with a plain assignment. Why arbitrary restrictions when the goal is to have great expressiveness? -manfred |
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | Manfred Nowak wrote:
> On writing the implementation of a map, where the Valuetype is a set, I had to stop on recognizing, that only opIndexAssign is permitted.
>
> I.e.:
> map[ key]+= element;
> has no possible overload.
>
> OpIndex delivers an rvalue and the only possibility to get an lvalue is in conjunction with a plain assignment.
>
> Why arbitrary restrictions when the goal is to have great expressiveness?
>
> -manfred
opIndexAssign was needed because D has no "inout" return type. It's a hack, if you ask me.
L.
|
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lionello Lunesu | "Lionello Lunesu" <lio@lunesu.remove.com> wrote in message news:eqhnb7$2tjh$2@digitaldaemon.com... > opIndexAssign was needed because D has no "inout" return type. It's a hack, if you ask me. Ehhh, I don't really think so.. having opIndexAssign is nice because you can do some processing on the value when it's assigned. How, for example would you do something as simple as this: void opIndexAssign(int value, int key) { mData[key] = value % 10; } using inout return values? In almost every one of my opIndexAssign overloads, I do some kind of checking or processing on the value before inserting it into the internal container. |
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | Manfred Nowak Wrote: > On writing the implementation of a map, where the Valuetype is a set, I had to stop on recognizing, that only opIndexAssign is permitted. To add opIndexAddAssign et al would be a step back towards the old C++ nightmare of providing lots of operator overloads where just one should suffice. > I.e.: > map[key]+= element; > has no possible overload. > > OpIndex delivers an rvalue and the only possibility to get an lvalue is in conjunction with a plain assignment. > > Why arbitrary restrictions when the goal is to have great expressiveness? I agree. It's been said about properties enough times, and the same should apply to array indexes. That is, qwert[yuiop] op= asdfg should be, in the lack of any overriding alternative (such as an op<op>Assign on the type of qwert[yuiop]), equivalent to qwert[yuiop] = qwert[yuiop] op asdfg except that qwert and yuiop are evaluated only once. Stewart. |
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Lionello Lunesu | Lionello Lunesu wrote:
> Manfred Nowak wrote:
>> On writing the implementation of a map, where the Valuetype is a set, I had to stop on recognizing, that only opIndexAssign is permitted.
>>
>> I.e.:
>> map[ key]+= element;
>> has no possible overload.
>>
>> OpIndex delivers an rvalue and the only possibility to get an lvalue is in conjunction with a plain assignment.
>>
>> Why arbitrary restrictions when the goal is to have great expressiveness?
>> -manfred
>
> opIndexAssign was needed because D has no "inout" return type. It's a hack, if you ask me.
It is a hack, but a useful one IMO. For example, say I want to insert an element in an AA only if the AA itself is used as an lvalue. ie.
auto x = myAA[key]; // return default value if not present
myAA[key] = x; // insert and assign
I'll admit that it would be much nicer if this worked for all applicable operator overloads without requiring separate signatures for each, but I'll take what I can get :-)
Sean
|
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jarrett Billingsley | "Jarrett Billingsley" <kb3ctd2@yahoo.com> wrote
> How, for example would you do something as simple as
> this:
>
> void opIndexAssign(int value, int key)
> {
> mData[key] = value % 10;
> }
>
> using inout return values?
The question is: what do really want to do and why do you have to mix up your intentions?
Your intention seems to bind an operation to the valuetype of the AA. But you have bound it to the AA directly and not to the valuetype.
The code
instance[ key]= value;
should be called approximately as
instance.opIndex_l(key)= typeof( mData[key]).opAssign( value)
In fact your example is not that easy because it is unclear what the
return value of opIndex( int) would be:
mData[key]
or
mData[key] * 10
or void as your opIndexAssign suggests?
-manfred
|
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | Manfred Nowak wrote:
> On writing the implementation of a map, where the Valuetype is a set, I had to stop on recognizing, that only opIndexAssign is permitted.
>
> I.e.:
> map[ key]+= element;
> has no possible overload.
>
> OpIndex delivers an rvalue and the only possibility to get an lvalue is in conjunction with a plain assignment.
>
> Why arbitrary restrictions when the goal is to have great expressiveness?
>
> -manfred
It could have some nasty side effect but, have opIndex return a struct/object that shadows the original and overloads opAddAssign.
class F
{
T[] i
class N
{
this(inout T l){j=&l;}
T* j;
T opAddAssign(T k)
{
j+=k;
return this;
}
}
N opIndex(int ind)
{
return new N(i[ind]);
}
}
On second thought, don't
|
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | Sean Kelly wrote:
> Lionello Lunesu wrote:
>> Manfred Nowak wrote:
>>> On writing the implementation of a map, where the Valuetype is a set, I had to stop on recognizing, that only opIndexAssign is permitted.
>>>
>>> I.e.:
>>> map[ key]+= element;
>>> has no possible overload.
>>>
>>> OpIndex delivers an rvalue and the only possibility to get an lvalue is in conjunction with a plain assignment.
>>>
>>> Why arbitrary restrictions when the goal is to have great expressiveness?
>>> -manfred
>>
>> opIndexAssign was needed because D has no "inout" return type. It's a hack, if you ask me.
>
> It is a hack, but a useful one IMO. For example, say I want to insert an element in an AA only if the AA itself is used as an lvalue. ie.
>
> auto x = myAA[key]; // return default value if not present
> myAA[key] = x; // insert and assign
>
> I'll admit that it would be much nicer if this worked for all applicable operator overloads without requiring separate signatures for each, but I'll take what I can get :-)
It's also useful for sparse vectors and matrices: you don't want to autoinsert stuff or throw when all you want is to read. Just return zero if it's not there.
Probably the principled thing to do is to allow two functions, one that returns lvalue and one that returns an rvalue, and have the compiler pick the appropriate one.
Andrei
|
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stewart Gordon | Stewart Gordon wrote:
> Manfred Nowak Wrote:
>
>> On writing the implementation of a map, where the Valuetype is a set, I had to stop on recognizing, that only opIndexAssign is permitted.
>
> To add opIndexAddAssign et al would be a step back towards the old C++ nightmare of providing lots of operator overloads where just one should suffice.
>
>> I.e.:
>> map[key]+= element;
>> has no possible overload.
>>
>> OpIndex delivers an rvalue and the only possibility to get an lvalue is in conjunction with a plain assignment.
>>
>> Why arbitrary restrictions when the goal is to have great expressiveness?
>
> I agree. It's been said about properties enough times, and the same should apply to array indexes. That is,
>
> qwert[yuiop] op= asdfg
>
> should be, in the lack of any overriding alternative (such as an op<op>Assign on the type of qwert[yuiop]), equivalent to
>
> qwert[yuiop] = qwert[yuiop] op asdfg
>
> except that qwert and yuiop are evaluated only once.
Same with .length.
arr.length += 2;
Andrei
|
February 09, 2007 Re: opIndexAddAssign? ... | ||||
---|---|---|---|---|
| ||||
Posted in reply to Manfred Nowak | "Manfred Nowak" <svv1999@hotmail.com> wrote in message news:eqi90k$kf5$1@digitaldaemon.com... > Your intention seems to bind an operation to the valuetype of the AA. But you have bound it to the AA directly and not to the valuetype. So, if all we had was opIndex that returned inout, you're suggesting I implement a new class for the value type of the internal container every time I want the behavior of index assigning to change? That seems a little overkill. Besides, the code I posted is an example. I'm just trying to say that an inout-returning-opIndex doesn't allow you to do anything with the value that's added to this. > The code > instance[ key]= value; > should be called approximately as > instance.opIndex_l(key)= typeof( mData[key]).opAssign( value) Again, if my internal data structure for instance is just an: int[] mData; then I can't have the "mData[key] = value % 10;" like in the opIndexAssign version. I'll have to create a proxy class to hold the data which modulos its value by 10 whenever opAssign is used, and make an array of that, and create all those class instances. God, it's starting to sound like Java. > In fact your example is not that easy because it is unclear what the > return value of opIndex( int) would be: > mData[key] > or > mData[key] * 10 That's not what I'm really getting at.. I'm talking about adding or setting an index of a container type, not getting one. > or void as your opIndexAssign suggests? I find chaining assignments and using assignments in conditionals (i.e. "if((x = nextThing()) == 0)") to be in bad form, so I always make my opXxxAssign and property setters return void so you can't do that. It's just a personal preference. |
Copyright © 1999-2021 by the D Language Foundation