digitalmars.D - PROPOSAL: Operator overloading by static member function
- oldrev (8/8) Oct 13 2007 It's a simple way to avoid using the ugly "opAdd_r", eg:
- Daniel Keep (4/14) Oct 13 2007 And how are you going to overload static opAdd_r, then?
- oldrev (8/27) Oct 13 2007 We do not need opAdd_r anymore, it will be overloaded by static opAdd.
- Nathan Reed (10/40) Oct 13 2007 I like the idea of a non-member function for overloading operators,
- Daniel Keep (21/51) Oct 13 2007 You didn't answer the first question. You haven't said how we're going
- Janice Caron (2/3) Oct 13 2007 Oh that is cool!
- Janice Caron (9/12) Oct 13 2007 I guess you could generalise that...
- Daniel Keep (10/27) Oct 13 2007 I did something similar in Python once (called it "Units") but got
- Janice Caron (18/24) Oct 14 2007 Well yeah. That's what I'd want - compile time dimension checking. And
- Reiner Pope (9/42) Oct 14 2007 Oskar Linde wrote one already: http://www.csc.kth.se/~ol/physical.d
- Janice Caron (9/10) Oct 14 2007 That's true. Put like that, static opAdd(), static opSub(), etc., do
- Reiner Pope (16/30) Oct 14 2007 Well, here's a ... good ... use:
- oldrev (5/65) Oct 14 2007 Awesome!
- BCS (8/25) Oct 14 2007 struct SIUnit(int d, int t, int m, int c=0, int k=0, int l=0)
- BCS (9/34) Oct 14 2007 I think I misread that (and I know I mistyped it):
- Janice Caron (12/20) Oct 14 2007 Returning to the original thread topic, how should the compiler react
- oldrev (4/31) Oct 14 2007 Noway, when you overloading a binary operator, it must has a Currency pa...
- Janice Caron (10/11) Oct 14 2007 Aha. I thought you might say that, so I've already planned out my
It's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }
Oct 13 2007
oldrev wrote:It's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }And how are you going to overload static opAdd_r, then? I really don't see any need for this; opAdd_r is perfectly fine. -- Daniel
Oct 13 2007
Daniel Keep Wrote:oldrev wrote:We do not need opAdd_r anymore, it will be overloaded by static opAdd. static A opAdd(A a, int i); static A opAdd(int i, A a); a+100 // it equals to opAdd(a, 100); 100+a //opAdd(100, a) Regards, - oldrevIt's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }And how are you going to overload static opAdd_r, then? I really don't see any need for this; opAdd_r is perfectly fine. -- Daniel
Oct 13 2007
oldrev wrote:Daniel Keep Wrote:I like the idea of a non-member function for overloading operators, since the definition looks more symmetric and avoids giving undue 'emphasis' to one of the values involved. On the other hand, this would be a breaking change and I'm not sure it's worth it. Also, one advantage of the current way of doing overloaded operators is that it enforces that operators that are supposed to be commutative, like +, can't be redefined to be noncommutative. Thanks, Nathan Reedoldrev wrote:We do not need opAdd_r anymore, it will be overloaded by static opAdd. static A opAdd(A a, int i); static A opAdd(int i, A a); a+100 // it equals to opAdd(a, 100); 100+a //opAdd(100, a) Regards, - oldrevIt's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }And how are you going to overload static opAdd_r, then? I really don't see any need for this; opAdd_r is perfectly fine. -- Daniel
Oct 13 2007
oldrev wrote:Daniel Keep Wrote:You didn't answer the first question. You haven't said how we're going to do this: struct Meters { real value; } struct m { static Meters opMul_r(real value) { return Meters(value); } } auto distance = 20*m; In your system, there's no way to have that since you can't have type arguments. And *yes*, there are people who use this kind of thing. Also, as Nathan pointed out, this would break basically *all* code that overloads any operators and for what? So we don't have to type "_r" and can no longer have static operator overloads? -- Danieloldrev wrote:We do not need opAdd_r anymore, it will be overloaded by static opAdd. static A opAdd(A a, int i); static A opAdd(int i, A a); a+100 // it equals to opAdd(a, 100); 100+a //opAdd(100, a) Regards, - oldrevIt's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }And how are you going to overload static opAdd_r, then? I really don't see any need for this; opAdd_r is perfectly fine. -- Daniel
Oct 13 2007
On 10/14/07, Daniel Keep <daniel.keep.lists gmail.com> wrote:auto distance = 20*m;Oh that is cool!
Oct 13 2007
On 10/14/07, Janice Caron <caron800 googlemail.com> wrote:On 10/14/07, Daniel Keep <daniel.keep.lists gmail.com> wrote:I guess you could generalise that... auto area = 100*m*m; auto velocity = 50*m/s; const G = 6.673e-11*m*m*m*/kg/s/s; ...and even do unit conversions... auto distance = 15*miles; /*converts to meters*/ Super duper. OK, I'm all in favor of keeping thing the way they are, coz that's just so brilliant.auto distance = 20*m;Oh that is cool!
Oct 13 2007
Janice Caron wrote:On 10/14/07, Janice Caron <caron800 googlemail.com> wrote:I did something similar in Python once (called it "Units") but got caught up on how exactly to encode transforms between different systems. Actually, I believe someone's done something like this for D before. Their goal, however, was *compile-time* checking of units. So, for example, you couldn't do this: auto v = 3*m/s; auto a = 9.81*m/(s*s); auto huh = v+a; -- DanielOn 10/14/07, Daniel Keep <daniel.keep.lists gmail.com> wrote:I guess you could generalise that... auto area = 100*m*m; auto velocity = 50*m/s; const G = 6.673e-11*m*m*m*/kg/s/s; ....and even do unit conversions... auto distance = 15*miles; /*converts to meters*/ Super duper. OK, I'm all in favor of keeping thing the way they are, coz that's just so brilliant.auto distance = 20*m;Oh that is cool!
Oct 13 2007
On 10/14/07, Daniel Keep <daniel.keep.lists gmail.com> wrote:Actually, I believe someone's done something like this for D before. Their goal, however, was *compile-time* checking of units. So, for example, you couldn't do this: auto v = 3*m/s; auto a = 9.81*m/(s*s); auto huh = v+a;Well yeah. That's what I'd want - compile time dimension checking. And it seems reasonably achievable with your system. And not to mention unit conversion, eg. auto d = 15*miles + 20*km; writefln(d.cm,"cm"); /* prints d in centimeters */ Of course, you'd really want it to be clever enough to understand when the units cancel out, e.g. auto n = (3*s) * (30*Hertz); /* n is real */ Could be we're looking for some sort of template struct, eg. struct SIUnit(int m,int s,int kg) { real r; } SIUnit!(1,0,0) x; // meters SIUnit!(1,-2,0) y; // meters per second per second SIUnit!(2,-2,1) z; // joules; Hmm...
Oct 14 2007
Janice Caron wrote:On 10/14/07, Daniel Keep <daniel.keep.lists gmail.com> wrote:Oskar Linde wrote one already: http://www.csc.kth.se/~ol/physical.d But you don't actually need static opMul for that. To quote two lines of it: const Length meter = {1}; ... Length l = 0.1 * meter; As you can see, it uses instance opMul. But still very cool. -- ReinerActually, I believe someone's done something like this for D before. Their goal, however, was *compile-time* checking of units. So, for example, you couldn't do this: auto v = 3*m/s; auto a = 9.81*m/(s*s); auto huh = v+a;Well yeah. That's what I'd want - compile time dimension checking. And it seems reasonably achievable with your system. And not to mention unit conversion, eg. auto d = 15*miles + 20*km; writefln(d.cm,"cm"); /* prints d in centimeters */ Of course, you'd really want it to be clever enough to understand when the units cancel out, e.g. auto n = (3*s) * (30*Hertz); /* n is real */ Could be we're looking for some sort of template struct, eg. struct SIUnit(int m,int s,int kg) { real r; } SIUnit!(1,0,0) x; // meters SIUnit!(1,-2,0) y; // meters per second per second SIUnit!(2,-2,1) z; // joules; Hmm...
Oct 14 2007
On 10/14/07, Reiner Pope <some address.com> wrote:But you don't actually need static opMul for that. To quote two lines of it:That's true. Put like that, static opAdd(), static opSub(), etc., do start to sound a bit silly. I can't see why you would ever need to write: x = A + y; where A was a type. Surely, any time you can imagine a use for that, you could probably do the same thing with A just being a variable? (The only one I can think of that has any real use is static opCall() -- and even that need would disappear if structs had constructors)
Oct 14 2007
Janice Caron wrote:On 10/14/07, Reiner Pope <some address.com> wrote:Well, here's a ... good ... use: struct foo { static bool opMul(foo* x) { return true;} } void main() { foo* p; assert(foo* p); // just checking that we declared p correctly foo* null; // hey, look! null really can be an identifier } Of course, you could do most of it with foo being a variable, but it's not anywhere near as expressive. :D -- ReinerBut you don't actually need static opMul for that. To quote two lines of it:That's true. Put like that, static opAdd(), static opSub(), etc., do start to sound a bit silly. I can't see why you would ever need to write: x = A + y; where A was a type. Surely, any time you can imagine a use for that, you could probably do the same thing with A just being a variable? (The only one I can think of that has any real use is static opCall() -- and even that need would disappear if structs had constructors)
Oct 14 2007
Daniel Keep Wrote:oldrev wrote:Awesome! Thanks to point it out! Regards, - oldrevDaniel Keep Wrote:You didn't answer the first question. You haven't said how we're going to do this: struct Meters { real value; } struct m { static Meters opMul_r(real value) { return Meters(value); } } auto distance = 20*m; In your system, there's no way to have that since you can't have type arguments. And *yes*, there are people who use this kind of thing. Also, as Nathan pointed out, this would break basically *all* code that overloads any operators and for what? So we don't have to type "_r" and can no longer have static operator overloads? -- Danieloldrev wrote:We do not need opAdd_r anymore, it will be overloaded by static opAdd. static A opAdd(A a, int i); static A opAdd(int i, A a); a+100 // it equals to opAdd(a, 100); 100+a //opAdd(100, a) Regards, - oldrevIt's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }And how are you going to overload static opAdd_r, then? I really don't see any need for this; opAdd_r is perfectly fine. -- Daniel
Oct 14 2007
Reply to Daniel,struct Meters { real value; } struct m { static Meters opMul_r(real value) { return Meters(value); } } auto distance = 20*m; In your system, there's no way to have that since you can't have type arguments. And *yes*, there are people who use this kind of thing.struct SIUnit(int d, int t, int m, int c=0, int k=0, int l=0) { static Meters opMul_r(real value) { } } const m = SIUnit!(1,0,0)(1.0);
Oct 14 2007
Reply to Benjamin,Reply to Daniel,I think I misread that (and I know I mistyped it): struct SIUnit(int d, int t, int m, int c=0, int k=0, int l=0) { } SIUnit!(d, t, m, c, k, l) opMul(int d, int t, int m, int c, int k, int l)(real value, SIUnit!(d, t, m, c, k, l) v2) { }struct Meters { real value; } struct m { static Meters opMul_r(real value) { return Meters(value); } } auto distance = 20*m; In your system, there's no way to have that since you can't have type arguments. And *yes*, there are people who use this kind of thing.struct SIUnit(int d, int t, int m, int c=0, int k=0, int l=0) { static Meters opMul_r(real value) { } } const m = SIUnit!(1,0,0)(1.0);
Oct 14 2007
On 10/13/07, oldrev <oldrev gmail.com> wrote:It's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }Returning to the original thread topic, how should the compiler react if I "cheat" and do struct Currency { private int m_value; public static Currency opAdd(int lhs, int rhs) { return Currency(lhs + rhs); } } I'm sure you can see the problem here. I've just redefined int + int. Surely, that can't be allowed?
Oct 14 2007
Janice Caron Wrote:On 10/13/07, oldrev <oldrev gmail.com> wrote:Noway, when you overloading a binary operator, it must has a Currency parameter at least. Regards, - oldrevIt's a simple way to avoid using the ugly "opAdd_r", eg: struct Currency { private int m_value; public static Currency opAdd(Currency lhs, Currency rhs) { return Currency(lhs.m_value + rhs.m_value); } }Returning to the original thread topic, how should the compiler react if I "cheat" and do struct Currency { private int m_value; public static Currency opAdd(int lhs, int rhs) { return Currency(lhs + rhs); } } I'm sure you can see the problem here. I've just redefined int + int. Surely, that can't be allowed?
Oct 14 2007
On 10/14/07, oldrev <oldrev gmail.com> wrote:Noway, when you overloading a binary operator, it must has a Currency parameter at least.Aha. I thought you might say that, so I've already planned out my response. If one of the parameters /has/ to be a Currency, then the best way to ensure that is to ditch the word "static", and bingo! - one Currency parameter /automatically/ at your disposal (it's called "this"). Job done. Of course, you still need to distinguish LHS from RHS, but that can be done easily and simply just by suffixing "_r" to the function name in the latter case. I call this new, revised proposal, the "status quo". :-)
Oct 14 2007