digitalmars.D - opXAssign overloading
- dsimcha (31/31) Oct 12 2009 It seems that D's operator overloading is a bit silly in some cases w.r....
- Robert Jacques (3/38) Oct 12 2009 Also, if you template both opX and opX_r you will always get a overload ...
- Don (8/54) Oct 13 2009 Yes, I posted a patch for that to the ng. It's very simple.
- Bill Baxter (25/80) Oct 13 2009 =3D
It seems that D's operator overloading is a bit silly in some cases w.r.t. opAddAssign, opSubAssign, etc. Consider the following example: struct Foo { Foo opAdd(Foo rhs) { return this; } } void main() { Foo foo; Foo bar; foo = foo + bar; // Works. foo += bar; // Doesn't work. } I'm thinking (not sure if this was proposed here before a while back and I just forgot where I heard it from) that the default behavior of someObject.opXAssign(otherStuff); should be to expand into someObject = someObject.opX(otherStuff); if opXAssign is not overloaded. Besides the programmer being too lazy to explicitly overload opXAssign, I just found another use case. Suppose you have a bunch of classes and you're overloading operators such that each call builds another layer of decorators. For example: class SomeClass { SomeClass opAdd(SomeClass rhs) { // SomeDecorator is a subclass of SomeClass. return new SomeDecorator(this, rhs); } } In this case, you *can't* overload SomeClass.opAddAssign in any reasonable way because you can't assign SomeDecorator to this, but translating someInstance.opAddAssign(someOtherInstance) into someInstance = someInstance.opAdd(someOtherInstance) makes perfect sense.
Oct 12 2009
On Tue, 13 Oct 2009 00:31:32 -0400, dsimcha <dsimcha yahoo.com> wrote:It seems that D's operator overloading is a bit silly in some cases w.r.t. opAddAssign, opSubAssign, etc. Consider the following example: struct Foo { Foo opAdd(Foo rhs) { return this; } } void main() { Foo foo; Foo bar; foo = foo + bar; // Works. foo += bar; // Doesn't work. } I'm thinking (not sure if this was proposed here before a while back and I just forgot where I heard it from) that the default behavior of someObject.opXAssign(otherStuff); should be to expand into someObject = someObject.opX(otherStuff); if opXAssign is not overloaded. Besides the programmer being too lazy to explicitly overload opXAssign, I just found another use case. Suppose you have a bunch of classes and you're overloading operators such that each call builds another layer of decorators. For example: class SomeClass { SomeClass opAdd(SomeClass rhs) { // SomeDecorator is a subclass of SomeClass. return new SomeDecorator(this, rhs); } } In this case, you *can't* overload SomeClass.opAddAssign in any reasonable way because you can't assign SomeDecorator to this, but translating someInstance.opAddAssign(someOtherInstance) into someInstance = someInstance.opAdd(someOtherInstance) makes perfect sense.Also, if you template both opX and opX_r you will always get a overload conflict.
Oct 12 2009
Robert Jacques wrote:On Tue, 13 Oct 2009 00:31:32 -0400, dsimcha <dsimcha yahoo.com> wrote:It seems that D's operator overloading is a bit silly in some cases w.r.t. opAddAssign, opSubAssign, etc. Consider the following example: struct Foo { Foo opAdd(Foo rhs) { return this; } } void main() { Foo foo; Foo bar; foo = foo + bar; // Works. foo += bar; // Doesn't work. } I'm thinking (not sure if this was proposed here before a while back and I just forgot where I heard it from) that the default behavior of someObject.opXAssign(otherStuff); should be to expand into someObject = someObject.opX(otherStuff); if opXAssign is not overloaded. Besides the programmer being too lazy to explicitly overload opXAssign, I just found another use case. Suppose you have a bunch of classes and you're overloading operators such that each call builds another layer of decorators. For example: class SomeClass { SomeClass opAdd(SomeClass rhs) { // SomeDecorator is a subclass of SomeClass. return new SomeDecorator(this, rhs); } } In this case, you *can't* overload SomeClass.opAddAssign in any reasonable way because you can't assign SomeDecorator to this, but translating someInstance.opAddAssign(someOtherInstance) into someInstance = someInstance.opAdd(someOtherInstance) makes perfect sense.Also, if you template both opX and opX_r you will always get a overload conflict.Yes, I posted a patch for that to the ng. It's very simple. There has been some discussion as to whether arithmetic operator overloading makes sense at all for reference types. My feeling is that if x = x + y; has a different meaning to x += y; then operator overloading doesn't make sense. But, perhaps with the decorator idea you are close to having a use case for classes where operator overloading makes sense?
Oct 13 2009
On Tue, Oct 13, 2009 at 2:30 AM, Don <nospam nospam.com> wrote:Robert Jacques wrote:dOn Tue, 13 Oct 2009 00:31:32 -0400, dsimcha <dsimcha yahoo.com> wrote:It seems that D's operator overloading is a bit silly in some cases w.r.t. opAddAssign, opSubAssign, etc. =A0Consider the following example: struct Foo { =A0 =A0Foo opAdd(Foo rhs) { =A0 =A0 =A0 =A0return this; =A0 =A0} } void main() { =A0 =A0Foo foo; =A0 =A0Foo bar; =A0 =A0foo =3D foo + bar; =A0// Works. =A0 =A0foo +=3D bar; =A0// Doesn't work. } I'm thinking (not sure if this was proposed here before a while back an==3DI just forgot where I heard it from) that the default behavior of someObject.opXAssign(otherStuff); should be to expand into someObject =thesomeObject.opX(otherStuff); if opXAssign is not overloaded. =A0Besides =dprogrammer being too lazy to explicitly overload opXAssign, I just foun=chanother use case. Suppose you have a bunch of classes and you're overloading operators su=ingthat each call builds another layer of decorators. =A0For example: class SomeClass { =A0 =A0SomeClass opAdd(SomeClass rhs) { =A0 =A0 =A0 // SomeDecorator is a subclass of SomeClass. =A0 =A0 =A0 return new SomeDecorator(this, rhs); =A0 =A0} } In this case, you *can't* overload SomeClass.opAddAssign in any reasonable way because you can't assign SomeDecorator to this, but translating someInstance.opAddAssign(someOtherInstance) into someInstance =3D someInstance.opAdd(someOtherInstance) makes perfect sense.Also, if you template both opX and opX_r you will always get a overload conflict.Yes, I posted a patch for that to the ng. It's very simple. There has been some discussion as to whether arithmetic operator overload=makes sense at all for reference types. My feeling is that if =A0x =3D x =+ y;has a different meaning to x +=3D y; then operator overloading doesn't ma=kesense. But, perhaps with the decorator idea you are close to having a use case f=orclasses where operator overloading makes sense?Well, I have implemented an N-d array-like type as a class before. I don't think it's the best way to do it, but someone might like to have a general array class they could override to behave as a matrix. There is such a thing in Numpy. I don't think it's the greatest idea in the world, but if you do make such a thing, then you want to be able to make +=3D identity preserving and =3D not. And that's how stuff works in Python in general. +=3D modifies an object, =3D changes its identity. So I wouldn't say it's nonsense to have such a rule. What you can say is that this better be true (to within numerical precision) x1 =3D x + y x +=3D y =3D=3D> x1 =3D=3D x --bb x+
Oct 13 2009