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.)
Ali
I 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









=?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> 