digitalmars.D.learn - Can i rewrite methods in one line?
- Ivan Agafonov (101/101) Sep 02 2012 struct Vector(T, uint size)
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (17/17) Sep 02 2012 In general, yes, you can construct and return at the same time. As you
- Ivan Agafonov (23/43) Sep 02 2012 I made a mistake here. This operators have already "onelined" :
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (16/21) Sep 02 2012 You meant it for opOpAssign, right?
- Ivan Agafonov (47/47) Sep 02 2012 Yeah! I did it!
- Ivan Agafonov (5/5) Sep 02 2012 Note that opBinary operators uses op= instead of op :
- Ivan Agafonov (5/5) Sep 02 2012 Note that opBinary operators uses op= instead of op :
struct Vector(T, uint size) { static assert(size >= 2 && size <= 4); static assert(__traits(isFloating, T); /// Vector components union { T[size] array = 0; struct { static if(size == 1) T x; static if(size == 2) T x, y; static if(size == 3) T x, y, z; static if(size == 4) T x, y, z, w; } } this (T rhs) { array[] = rhs; } this (T[] components...) { array[] = components[]; } this (T* components) { array[] = components[0..size]; } this (T[size] components) { array[] = components[]; } this (Vector rhs) { array[] = rhs.array[]; } Vector opUnary(string op) () if (op == "-") { Vector tmp; tmp.array[] = -array[]; return tmp; } Vector opBinary(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { Vector tmp; tmp.array[] = mixin("array[] "~op~" rhs.array[]"); return tmp; } Vector opBinary(string op) (T rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { Vector tmp; tmp.array[] = mixin("array[] "~op~" rhs"); return tmp; } ref Vector opOpAssign(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs.array[];"); return this; } ref Vector opOpAssign(string op) (T rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs;"); return this; } } I want to rewrite it in something like this: struct Vector(T, uint size) { static assert(size >= 2 && size <= 4); static assert(__traits(isFloating, T); /// Vector components union { T[size] array = 0; struct { static if(size == 1) T x; static if(size == 2) T x, y; static if(size == 3) T x, y, z; static if(size == 4) T x, y, z, w; } } this (T rhs) { array[] = rhs; } this (T[] components...) { array[] = components[]; } this (T* components) { array[] = components[0..size]; } this (T[size] components) { array[] = components[]; } this (Vector rhs) { array[] = rhs.array[]; } Vector opUnary(string op) () if (op == "-") { return Vector(-array); } Vector opBinary(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { return Vector(mixin("array[] "~op~" rhs.array[]")); } Vector opBinary(string op) (T rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { return Vector(mixin("array[] "~op~" rhs")); } ref Vector opOpAssign(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { return Vector(mixin("array[] "~op~"= rhs.array[]")); } ref Vector opOpAssign(string op) (T rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { return Vector(mixin("array[] "~op~"= rhs")); } } Main goal is to return and constuct in one place. Can I do so? I now that there will take place compiller optimisations and both versions will be the same, but what if not? PS: Sorry for my english.
Sep 02 2012
In general, yes, you can construct and return at the same time. As you said, in a language like D where source code is almost always visible, the compiler can apply many optimization techniques. However, some of your operators ended up having semantic differences. opOpAssign used to return a reference to this object: ref Vector opOpAssign(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs.array[];"); return this; } opOpAssign now returns a reference to a newly-created temporary object: ref Vector opOpAssign(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { return Vector(mixin("array[] "~op~"= rhs.array[]")); } (It is the same for the other opOpAssign.) Ali
Sep 02 2012
On Monday, 3 September 2012 at 02:40:09 UTC, Ali Çehreli wrote:In general, yes, you can construct and return at the same time. As you said, in a language like D where source code is almost always visible, the compiler can apply many optimization techniques. However, some of your operators ended up having semantic differences. opOpAssign used to return a reference to this object: ref Vector opOpAssign(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs.array[];"); return this; } opOpAssign now returns a reference to a newly-created temporary object: ref Vector opOpAssign(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { return Vector(mixin("array[] "~op~"= rhs.array[]")); } (It is the same for the other opOpAssign.) AliI made a mistake here. This operators have already "onelined" : ref Vector opAssign(Vector rhs) { array[] = rhs.array[]; return this; } ref Vector opAssign(T[size] rhs) { array[] = rhs[]; return this; } ref Vector opOpAssign(string op) (T[size] rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs[];"); return this; } ref Vector opOpAssign(string op) (Vector rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs.array[];"); return this; } ref Vector opOpAssign(string op) (T rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs;"); return this; } But i can't write something like this: return Vector(mixin("array[] "~op~"= rhs.array[]")); because array[] op= rhs.array[] is not a right expression it does not return an array, it can only be used in assigment to slice like this[]. And expression array op= rhs.array does not make sense too.
Sep 02 2012
On 09/02/2012 07:57 PM, Ivan Agafonov wrote:ref Vector opOpAssign(string op) (T rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs;"); return this; } But i can't write something like this: return Vector(mixin("array[] "~op~"= rhs.array[]"));You meant it for opOpAssign, right? opOpAssign must 'return this', not a new object. Otherwise chaining operators would be confusing: (v0 += v1) *= v2; If the += operation could return a new object (which it can't), then *= would be operating on that. So your existing version is correct: ref Vector opOpAssign(string op) (T[size] rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs[];"); return this; } But if you don't care about chained operations you can also return void: void opOpAssign(string op) (T[size] rhs) if(op == "+" || op == "-" || op == "*" || op == "/") { mixin("array[] "~op~"= rhs[];"); } Ali
Sep 02 2012
Yeah! I did it! How about this solution? What do you think? static assert(size >= 2 && size <= 4); static assert(__traits(isFloating, T)); /// Vector components union { T[size] array = 0; struct { static if(size == 2) T x, y; static if(size == 3) T x, y, z; static if(size == 4) T x, y, z, w; } } this (T rhs) { array[] = rhs; } this (T[] components...) { array[] = components[]; } this (T* components) { array[] = components[0..size]; } this (T[size] components) { array[] = components[]; } this (Vector rhs) { array[] = rhs.array[]; } private static bool isMathOp(string op) { return (op == "+" || op == "-" || op == "*" || op == "/"); } Vector opUnary(string op) () if (op == "-") { return Vector(array.dup[] = -array[]); } Vector opBinary(string op) (Vector rhs) if(isMathOp(op)) { return Vector(mixin("array.dup[] "~op~"= rhs.array[]")); } Vector opBinary(string op) (T rhs) if(isMathOp(op)) { return Vector(mixin("array.dup[] "~op~"= rhs")); } ref Vector opAssign(Vector rhs) { array[] = rhs.array[]; return this; } ref Vector opAssign(T[size] rhs) { array[] = rhs[]; return this; } ref Vector opOpAssign(string op) (T[size] rhs) if(isMathOp(op)) { mixin("array[] "~op~"= rhs[];"); return this; } ref Vector opOpAssign(string op) (Vector rhs) if(isMathOp(op)) { mixin("array[] "~op~"= rhs.array[];"); return this; } ref Vector opOpAssign(string op) (T rhs) if(isMathOp(op)) { mixin("array[] "~op~"= rhs;"); return this; } ... Some other op's ... }
Sep 02 2012
Note that opBinary operators uses op= instead of op : Vector opBinary(string op) (Vector rhs) if(isMathOp(op)) { return Vector(mixin("array.dup[] "~op~"= rhs.array[]")); } Vector opBinary(string op) (T rhs) if(isMathOp(op)) { return Vector(mixin("array.dup[] "~op~"= rhs")); }
Sep 02 2012
Note that opBinary operators uses op= instead of op : Vector opBinary(string op) (Vector rhs) if(isMathOp(op)) { return Vector(mixin("array.dup[] "~op~"= rhs.array[]")); } Vector opBinary(string op) (T rhs) if(isMathOp(op)) { return Vector(mixin("array.dup[] "~op~"= rhs")); }
Sep 02 2012