www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - opDispatch is grand!

reply so <so so.do> writes:
struct vector(T, uint N) {
	auto opDispatch(string s) const {
		static if(N>0 && ("x"==s || "r"==s)) return v_[0];
		static if(N>1 && ("y"==s || "g"==s)) return v_[0];
		static if(N>2 && ("z"==s || "b"==s)) return v_[0];
		static if(N>3 && ("w"==s || "a"==s)) return v_[0];
		static assert("boom!");
	}
private:
	T[N] v_;
}

No unions, clean and all!
Then why do we need properties?




When i am sick, i try distract myself, this is one of those times, so just ignore me if it doesn't make sense :) Thanks! -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Apr 10 2010
next sibling parent so <so so.do> writes:
Because i made a mistake!

struct vector(T, uint N) {
	auto opDispatch(string s) const {
		static if(N>0 && ("x"==s || "r"==s)) return v_[0];
		static if(N>1 && ("y"==s || "g"==s)) return v_[1];
		static if(N>2 && ("z"==s || "b"==s)) return v_[2];
		static if(N>3 && ("w"==s || "a"==s)) return v_[3];
		static assert("boom!");
	}
private:
	T[N] v_;
}

Better...

On Sun, 11 Apr 2010 02:49:14 +0400, so <so so.do> wrote:

 struct vector(T, uint N) {
 	auto opDispatch(string s) const {
 		static if(N>0 && ("x"==s || "r"==s)) return v_[0];
 		static if(N>1 && ("y"==s || "g"==s)) return v_[0];
 		static if(N>2 && ("z"==s || "b"==s)) return v_[0];
 		static if(N>3 && ("w"==s || "a"==s)) return v_[0];
 		static assert("boom!");
 	}
 private:
 	T[N] v_;
 }

 No unions, clean and all!
 Then why do we need properties?




When i am sick, i try distract myself, this is one of those times, so just ignore me if it doesn't make sense :) Thanks!

-- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Apr 10 2010
prev sibling parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 04/10/2010 05:49 PM, so wrote:
 struct vector(T, uint N) {
 auto opDispatch(string s) const {
 static if(N>0 && ("x"==s || "r"==s)) return v_[0];
 static if(N>1 && ("y"==s || "g"==s)) return v_[0];
 static if(N>2 && ("z"==s || "b"==s)) return v_[0];
 static if(N>3 && ("w"==s || "a"==s)) return v_[0];
 static assert("boom!");
 }
 private:
 T[N] v_;
 }

 No unions, clean and all!
 Then why do we need properties?

Can you get vector!(int,3) v; v.x = 1; to work? The closest I can get is struct vector(T, uint N) { ref T opDispatch(string s )() { static if(N>0 && ("x"==s || "r"==s)) return v_[0]; static if(N>1 && ("y"==s || "g"==s)) return v_[1]; static if(N>2 && ("z"==s || "b"==s)) return v_[2]; static if(N>3 && ("w"==s || "a"==s)) return v_[3]; static assert("boom!"); } private: T[N] v_; } .. vector!(int, 3) v; v.x() = 1; when DMD sees v.x = 1; it tries to rewrite it as v.x(1); And I can't figure out how to overload opDispatch
Apr 10 2010
parent reply BCS <none anon.com> writes:
Hello Ellery,

 On 04/10/2010 05:49 PM, so wrote:
 
 struct vector(T, uint N) {
 auto opDispatch(string s) const {
 static if(N>0 && ("x"==s || "r"==s)) return v_[0];
 static if(N>1 && ("y"==s || "g"==s)) return v_[0];
 static if(N>2 && ("z"==s || "b"==s)) return v_[0];
 static if(N>3 && ("w"==s || "a"==s)) return v_[0];
 static assert("boom!");
 }
 private:
 T[N] v_;
 }
 No unions, clean and all!
 Then why do we need properties?

vector!(int,3) v; v.x = 1; to work? The closest I can get is struct vector(T, uint N) { ref T opDispatch(string s )() { static if(N>0 && ("x"==s || "r"==s)) return v_[0]; static if(N>1 && ("y"==s || "g"==s)) return v_[1]; static if(N>2 && ("z"==s || "b"==s)) return v_[2]; static if(N>3 && ("w"==s || "a"==s)) return v_[3]; static assert("boom!"); } private: T[N] v_; } .. vector!(int, 3) v; v.x() = 1; when DMD sees v.x = 1; it tries to rewrite it as v.x(1); And I can't figure out how to overload opDispatch

I think you might be able to do: ret!(T) opDispatch(string s, T)(T t) { ... } and then switch internally based on T. -- ... <IXOYE><
Apr 10 2010
parent reply Ellery Newcomer <ellery-newcomer utulsa.edu> writes:
On 04/10/2010 09:04 PM, BCS wrote:
 Hello Ellery,


 I think you might be able to do:

 ret!(T) opDispatch(string s, T)(T t) { ... }

 and then switch internally based on T.

I don't think so; it looks like dmd rewrites invocations as opDispatch!("x")
Apr 10 2010
next sibling parent BCS <none anon.com> writes:
Hello Ellery,

 On 04/10/2010 09:04 PM, BCS wrote:
 
 Hello Ellery,
 
 I think you might be able to do:
 
 ret!(T) opDispatch(string s, T)(T t) { ... }
 
 and then switch internally based on T.
 

opDispatch!("x")

Oops, that should have been: ret!(T) opDispatch(string s, T...)(T t) { ... } -- ... <IXOYE><
Apr 10 2010
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0003255549fac6e61b0483fae877
Content-Type: text/plain; charset=ISO-8859-1

On Sun, Apr 11, 2010 at 04:27, BCS <none anon.com> wrote:

 Hello Ellery,

 Oops, that should have been:


 ret!(T) opDispatch(string s, T...)(T t) { ... }

 I couldn't make (string s, T...) to work, though that was the most natural

Instead, I had to rely on variadic functions: struct vector(T, uint N) { auto ref opDispatch(string s)(...) if (s.length == 1) { // I don't think the auto ref is still necessary. It appeared during iterations on this. static if(N>0 && ("x"==s || "r"==s)) { if (_arguments.length == 1) { if (_arguments[0] == typeid(T)) { v_[0] = *cast(T*)_argptr; } else { throw new Exception("Bad argument for vector.x, should be of type " ~ T.stringof); } } return v_[0]; } static if(N>1 && ("y"==s || "g"==s)) return v_[1]; // TODO: the same for y,z and w... static if(N>2 && ("z"==s || "b"==s)) return v_[2]; static if(N>3 && ("w"==s || "a"==s)) return v_[3]; static assert("boom!"); } T[n] v_; } void main() { vector!(int, 3) v; writeln(v.x); // 0 v.x = 1; writeln(v.x); // 1 } What's even more grand, is when you use opDispatch to generate the function for you. In this case, you can get swizzling (sp?): // first, a helper template, needed to get a static foreach. Useful everywhere, this template. // alias it self to TypeTuple!(T,T,T,...) with n Ts template TypeNuple(T, size_t n) { static if(n == 0) { alias TypeTuple!() TypeNuple; } else { alias TypeTuple!(T,TypeNuple!(T, n-1)) TypeNuple; } } // change: Vector with a 'V' // change: opDispatch(string s) if (s.length >1) struct Vector(T, uint N) { auto ref opDispatch(string s)(...) if (s.length == 1) { static if(N>0 && ("x"==s || "r"==s)) return v_[0]; static if(N>1 && ("y"==s || "g"==s)) return v_[1]; static if(N>2 && ("z"==s || "b"==s)) return v_[2]; static if(N>3 && ("w"==s || "a"==s)) return v_[3]; static assert("boom!"); } T[s.length] opDispatch(string s)() if (s.length > 1) { // s.length> 1: will construct the value from the first opDispatch T[s.length] result; alias TypeNuple!(T, s.length) TN; // to get a compile-time foreach foreach(i, Type; TN) { result[i] = this.opDispatch!(s[i..i+1])(); // that way, i is a CT index. I use s[i..i+1] to get a string } return result; } private: T[N] v_; } // and then, a handy helper function to create a Vector: // need import std.traits; Vector!(CommonType!T, T.length) vector(T...)(T args) if (is(CommonType!T)) { return Vector!(CommonType!T, T.length)([args]); // args is a tuple, so [args] dumps it into an array } usage: void main() { auto v = vector(1,2,3); // deduced by the compiler to be a Vector!(int, 3) auto v2 = vector(1.2,2,3,4); // deduced by the compiler to be Vector!(double, 4) // and then, swizzling writeln(v.yzx); // "231" writeln(v.xxxx); // "1111" } --0003255549fac6e61b0483fae877 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><div class=3D"gmail_quote">On Sun, Apr 11, 2010 at 04:27, BCS <span dir= =3D"ltr">&lt;<a href=3D"mailto:none anon.com">none anon.com</a>&gt;</span> = wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.= 8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> Hello Ellery,<div><div></div><div class=3D"h5"><br></div></div> Oops, that should have been:<div><div></div><div class=3D"h5"><br> <br> ret!(T) opDispatch(string s, T...)(T t) { ... }<font color=3D"#888888"><br> </font><br></div></div></blockquote><div>I couldn&#39;t make (string s, T..= .) to work, though that was the most natural way to do it. <br>Instead, I h= ad to rely on variadic functions:<br><br>struct vector(T, uint N) {<br> =A0=A0=A0 auto ref opDispatch(string s)(...) if (s.length =3D=3D 1) { // I = don&#39;t think the auto ref is still necessary. It appeared during iterati= ons on this.<br>=A0=A0=A0=A0=A0=A0=A0 static if(N&gt;0 &amp;&amp; (&quot;x&= quot;=3D=3Ds || &quot;r&quot;=3D=3Ds)) {<br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 if (_arguments.length =3D=3D 1) {<br>=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 if (_arguments[0] =3D=3D typeid(= T)) {<br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 v_[0] = =3D *cast(T*)_argptr;<br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }<br=
=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 else {<br>=A0=A0=A0=A0=A0=A0=

ent for vector.x, should be of type &quot; ~ T.stringof);<br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 }<br>=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 }<br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return v_[0];<br>=A0=A0=A0= =A0=A0=A0 }<br>=A0=A0=A0=A0=A0=A0 static if(N&gt;1 &amp;&amp; (&quot;y&quot= ;=3D=3Ds || &quot;g&quot;=3D=3Ds)) return v_[1]; // TODO: the same for y,z = and w...<br>=A0=A0=A0=A0=A0=A0 static if(N&gt;2 &amp;&amp; (&quot;z&quot;= =3D=3Ds || &quot;b&quot;=3D=3Ds)) return v_[2];<br> =A0=A0=A0=A0=A0=A0 static if(N&gt;3 &amp;&amp; (&quot;w&quot;=3D=3Ds || &qu= ot;a&quot;=3D=3Ds)) return v_[3];<br><br>=A0=A0=A0=A0=A0=A0 static assert(&= quot;boom!&quot;);<br>=A0=A0=A0 }<br><br>=A0 T[n] v_;<br>}<br><br>void main= () {<br>=A0=A0 vector!(int, 3) v;<br>=A0=A0 writeln(v.x); //=A0 0<br> =A0=A0 v.x =3D 1;<br>=A0=A0 writeln(v.x); // 1<br>}<br><br><br>What&#39;s e= ven more grand, is when you use opDispatch to generate the function for you= . In this case, you can get swizzling (sp?):<br><br>// first, a helper temp= late, needed to get a static foreach. Useful everywhere, this template.<br> // alias it self to TypeTuple!(T,T,T,...) with n Ts<br>template TypeNuple(T= , size_t n) {<br>=A0=A0=A0 static if(n =3D=3D 0) {<br>=A0=A0=A0=A0=A0=A0=A0= alias TypeTuple!() TypeNuple;<br>=A0=A0=A0 }<br>=A0=A0=A0 else {<br>=A0=A0= =A0=A0=A0=A0=A0 alias TypeTuple!(T,TypeNuple!(T, n-1)) TypeNuple;<br> =A0=A0=A0 }<br>}<br><br>// change: Vector with a &#39;V&#39;<br>// change: = opDispatch(string s) if (s.length &gt;1)<br>struct Vector(T, uint N) {<br>= =A0=A0=A0 auto ref opDispatch(string s)(...) if (s.length =3D=3D 1) {<br>= =A0=A0=A0=A0=A0=A0 static if(N&gt;0 &amp;&amp; (&quot;x&quot;=3D=3Ds || &qu= ot;r&quot;=3D=3Ds)) return v_[0];<br> =A0=A0=A0=A0=A0=A0 static if(N&gt;1 &amp;&amp; (&quot;y&quot;=3D=3Ds || &qu= ot;g&quot;=3D=3Ds)) return v_[1];<br>=A0=A0=A0=A0=A0=A0 static if(N&gt;2 &a= mp;&amp; (&quot;z&quot;=3D=3Ds || &quot;b&quot;=3D=3Ds)) return v_[2];<br>= =A0=A0=A0=A0=A0=A0 static if(N&gt;3 &amp;&amp; (&quot;w&quot;=3D=3Ds || &qu= ot;a&quot;=3D=3Ds)) return v_[3];<br> <br>=A0=A0=A0=A0=A0=A0 static assert(&quot;boom!&quot;);<br>=A0=A0=A0 }<br>= <br>=A0=A0=A0 T[s.length] opDispatch(string s)() if (s.length &gt; 1) { // = s.length&gt; 1: will construct the value from the first opDispatch<br>=A0= =A0=A0=A0=A0=A0=A0 T[s.length] result;<br> =A0=A0=A0=A0=A0=A0=A0 alias TypeNuple!(T, s.length) TN; // to get a compile= -time foreach<br>=A0=A0=A0=A0=A0=A0=A0 foreach(i, Type; TN) {<br>=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 result[i] =3D this.opDispatch!(s[i..i+1])(); // th= at way, i is a CT index. I use s[i..i+1] to get a string<br> =A0=A0=A0=A0=A0=A0=A0 }<br>=A0=A0=A0=A0=A0=A0=A0 return result;<br>=A0=A0= =A0 }<br><br>=A0=A0=A0 private:<br>=A0=A0=A0 T[N] v_;<br>}<br><br>// and th= en, a handy helper function to create a Vector:<br>// need import std.trait= s;<br>Vector!(CommonType!T, T.length) vector(T...)(T args) if (is(CommonTyp= e!T))<br> {<br>=A0=A0=A0 return Vector!(CommonType!T, T.length)([args]); // args is a= tuple, so [args] dumps it into an array<br>}<br><br>usage:<br><br>void mai= n() {<br>=A0=A0=A0 auto v =3D vector(1,2,3); // deduced by the compiler to = be a Vector!(int, 3)<br> =A0=A0 auto v2 =3D vector(1.2,2,3,4); // deduced by the compiler to be Vect= or!(double, 4)<br><br>// and then, swizzling<br>=A0=A0 writeln(v.yzx); // &= quot;231&quot;<br>=A0 writeln(v.xxxx); // &quot;1111&quot;<br><br>}<br><br>= </div></div> --0003255549fac6e61b0483fae877--
Apr 11 2010