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>
 =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> 