www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Comparing Two Type Tuples

reply Daniel Ribeiro Maciel <danielmaciel gmail.com> writes:
Heya ppl!

I was wondering how could I write a function that takes two Type
Tuples as arguments and returns true if they are match.

Could anyone help me with this?

Thanks!
Apr 04 2010
next sibling parent reply Justin Spahr-Summers <Justin.SpahrSummers gmail.com> writes:
On Sun, 4 Apr 2010 21:05:49 +0000 (UTC), Daniel Ribeiro Maciel 
<danielmaciel gmail.com> wrote:
 
 Heya ppl!
 
 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.
 
 Could anyone help me with this?
 
 Thanks!

You can really only pass a single type tuple to a template, but you can work around it by passing a length and then comparing two parts of a combined tuple. For instance: import std.stdio; import std.typetuple; void compare(uint LEN, TL ...) () { writefln("%s", is(TL[0 .. LEN] == TL[LEN .. $])); } void main() { alias TypeTuple!(int, double, char[]) tupleA; alias TypeTuple!(int, double, char[]) tupleB; alias TypeTuple!(int, double, char*) tupleC; compare!(tupleA.length, tupleA, tupleB); compare!(tupleA.length, tupleA, tupleC); } will output "true" then "false."
Apr 04 2010
next sibling parent Daniel Ribeiro Maciel <danielmaciel gmail.com> writes:
Wow! Nice! Thanks a lot!
Apr 04 2010
prev sibling next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Justin Spahr-Summers:
 void compare(uint LEN, TL ...) () {
     writefln("%s", is(TL[0 .. LEN] == TL[LEN .. $]));
 }

That's the best piece of D code I've seen this week :-) And I didn't know the is(==) works among tuples too. So far Walter has shown no interest in fixing the bad flattening semantics of tuples. Maybe it's a hard thing to implement. Bye, bearophile
Apr 04 2010
prev sibling parent bearophile <bearophileHUGS lycos.com> writes:
Philippe Sigaud:
 Since to be equal, they must have the same length, you can even get rid of
 the 'len' part and cut in the middle:

But if their length is not equal that can cause bugs. Bye, bearophile
Apr 05 2010
prev sibling next sibling parent Robert Clipsham <robert octarineparrot.com> writes:
On 04/04/10 22:05, Daniel Ribeiro Maciel wrote:
 Heya ppl!

 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.

 Could anyone help me with this?

 Thanks!

Based on Justin's code, I came up with this to remove the need to pass the length of the TypeTuple: ---- import std.typetuple; alias TypeTuple!(int, double, char[]) tupleA; alias TypeTuple!(int, double, char[]) tupleB; alias TypeTuple!(int, double, char*) tupleC; // Method 1: write an is() each time pragma(msg, (is(tupleA == tupleB)).stringof); pragma(msg, (is(tupleA == tupleC)).stringof); template compare(string t1, string t2) { enum compare = mixin("is("~t1~"=="~t2~")"); } // Method 2: Use the above template and pass strings pragma( msg, compare!("tupleA", "tupleB") ); pragma( msg, compare!("tupleA", "tupleC") ); ----
Apr 04 2010
prev sibling next sibling parent reply "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Daniel Ribeiro Maciel <danielmaciel gmail.com> wrote:

 Heya ppl!

 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.

 Could anyone help me with this?

 Thanks!

This should work, but doesn't (filing a bugzilla about it now): template compareTuple( T... ) { template compareTuple( U... ) { enum bool compareTuple = is( T == U ); } } static assert( compareTuple!( int, float )!( int, float ) ); However, this works: alias compareTuple!( int, float ) foo; static assert( foo!( int, float ) ); -- Simen
Apr 04 2010
parent BCS <none anon.com> writes:
Hello Simen,


 This should work, but doesn't (filing a bugzilla about it now):
 
 template compareTuple( T... ) {
 template compareTuple( U... ) {
 enum bool compareTuple = is( T == U );
 }
 }
 static assert( compareTuple!( int, float )!( int, float ) );

It does work if you rename the inner template to something like "with". -- ... <IXOYE><
Apr 04 2010
prev sibling next sibling parent "Simen kjaeraas" <simen.kjaras gmail.com> writes:
Simen kjaeraas <simen.kjaras gmail.com> wrote:

 Daniel Ribeiro Maciel <danielmaciel gmail.com> wrote:

 Heya ppl!

 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.

 Could anyone help me with this?

 Thanks!

This should work, but doesn't (filing a bugzilla about it now): template compareTuple( T... ) { template compareTuple( U... ) { enum bool compareTuple = is( T == U ); } } static assert( compareTuple!( int, float )!( int, float ) ); However, this works: alias compareTuple!( int, float ) foo; static assert( foo!( int, float ) );

There. http://d.puremagic.com/issues/show_bug.cgi?id=4061 -- Simen
Apr 04 2010
prev sibling next sibling parent reply BCS <none anon.com> writes:
Hello Daniel,

 Heya ppl!
 
 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.
 
 Could anyone help me with this?
 
 Thanks!

here is my untested vertion: template Compare(T...) { template With(U...) { static if(T.length != U.lenght) const bool With = false; else static if(T.length == 0) const bool With = true; else static if(is(T[0] == U[0])) const bool With = Compare!(T[1..$]).With!(U[1..$]); else const bool With = false; } } use like: Compare!(int, float, myStruct).With(alias1,alias2,typeArg) -- ... <IXOYE><
Apr 04 2010
parent reply Justin Spahr-Summers <Justin.SpahrSummers gmail.com> writes:
On Mon, 5 Apr 2010 02:59:15 +0000 (UTC), BCS <none anon.com> wrote:
 
 Hello Daniel,
 
 Heya ppl!
 
 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.
 
 Could anyone help me with this?
 
 Thanks!

here is my untested vertion: template Compare(T...) { template With(U...) { static if(T.length != U.lenght) const bool With = false; else static if(T.length == 0) const bool With = true; else static if(is(T[0] == U[0])) const bool With = Compare!(T[1..$]).With!(U[1..$]); else const bool With = false; } } use like: Compare!(int, float, myStruct).With(alias1,alias2,typeArg)

Definitely a lot cleaner. I'm curious, though... is there a reason to avoid is(T == U)?
Apr 05 2010
next sibling parent bearophile <bearophileHUGS lycos.com> writes:
Justin Spahr-Summers:
 Definitely a lot cleaner. I'm curious, though... is there a reason to 
 avoid is(T == U)?

I agree, I think the best answer is to not use a function/template, and just use the is(==) operator: import std.stdio: writeln; import std.typetuple; void main() { alias TypeTuple!(int, double, char[]) A; alias TypeTuple!(int, double, char[]) B; alias TypeTuple!(int, double, char*) C; alias TypeTuple!(int, double) D; writeln(is(A == B)); writeln(is(A == C)); writeln(is(A == D)); } Bye, bearophile
Apr 05 2010
prev sibling parent reply BCS <none anon.com> writes:
Hello Justin Spahr-Summers,

 On Mon, 5 Apr 2010 02:59:15 +0000 (UTC), BCS <none anon.com> wrote:
 
 Hello Daniel,
 
 Heya ppl!
 
 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.
 
 Could anyone help me with this?
 
 Thanks!
 

template Compare(T...) { template With(U...) { static if(T.length != U.lenght) const bool With = false; else static if(T.length == 0) const bool With = true; else static if(is(T[0] == U[0])) const bool With = Compare!(T[1..$]).With!(U[1..$]); else const bool With = false; } } use like: Compare!(int, float, myStruct).With(alias1,alias2,typeArg)

avoid is(T == U)?

I dind't know it worked? -- ... <IXOYE><
Apr 05 2010
parent reply Justin Spahr-Summers <Justin.SpahrSummers gmail.com> writes:
On Mon, 5 Apr 2010 15:47:10 +0000 (UTC), BCS <none anon.com> wrote:
 
 Hello Justin Spahr-Summers,
 
 On Mon, 5 Apr 2010 02:59:15 +0000 (UTC), BCS <none anon.com> wrote:
 
 Hello Daniel,
 
 Heya ppl!
 
 I was wondering how could I write a function that takes two Type
 Tuples as arguments and returns true if they are match.
 
 Could anyone help me with this?
 
 Thanks!
 

template Compare(T...) { template With(U...) { static if(T.length != U.lenght) const bool With = false; else static if(T.length == 0) const bool With = true; else static if(is(T[0] == U[0])) const bool With = Compare!(T[1..$]).With!(U[1..$]); else const bool With = false; } } use like: Compare!(int, float, myStruct).With(alias1,alias2,typeArg)

avoid is(T == U)?

I dind't know it worked?

It seemed to when I tested the snippet that I sent, but it might've just been luck of the draw, and in reality fail silently on certain edge cases. I'm really not sure.
Apr 05 2010
parent BCS <none anon.com> writes:
Hello Justin Spahr-Summers,

 On Mon, 5 Apr 2010 15:47:10 +0000 (UTC), BCS <none anon.com> wrote:
 
 I dind't know it worked?
 

just been luck of the draw, and in reality fail silently on certain edge cases. I'm really not sure.

While it's nice to see people questioning if something exists just because I don't know about it :), I should point out that there are many corners of D I have yet to explore. In this case, given that several people suggested it, I think it does work. (And if not, it should.) -- ... <IXOYE><
Apr 06 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--00151743f7ce655aaa04837b21e5
Content-Type: text/plain; charset=ISO-8859-1

On Sun, Apr 4, 2010 at 23:23, Justin Spahr-Summers <
Justin.SpahrSummers gmail.com> wrote:

 You can really only pass a single type tuple to a template, but you can
 work around it by passing a length and then comparing two parts of a
 combined tuple. For instance:

 import std.stdio;
 import std.typetuple;

 void compare(uint LEN, TL ...) () {
    writefln("%s", is(TL[0 .. LEN] == TL[LEN .. $]));
 }

the 'len' part and cut in the middle: bool compare(TT...)() { static if (TT.length % 2 == 0 && is(TT[0..$/2] == TT[$/2..$])) return true; else return false; } That's useful to compare two functions: template sameArgs(alias fun1, alias fun2) { static if (compare!(ParameterTypeTuple!fun1, ParameterTypeTuple!fun2)) enum bool sameArgs = true; else enum bool sameArgs = false; } (I think we could use std.traits.Select to manage this kind of static ifs) Philippe --00151743f7ce655aaa04837b21e5 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Sun, Apr 4, 2010 at 23:23, Justin Spahr-Summe= rs <span dir=3D"ltr">&lt;<a href=3D"mailto:Justin.SpahrSummers gmail.com">J= ustin.SpahrSummers gmail.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;"> <div><div></div>You can really only pass a single type tuple to a template,= but you can<br></div> work around it by passing a length and then comparing two parts of a<br> combined tuple. For instance:<br> <br> import std.stdio;<br> import std.typetuple;<br> <br> void compare(uint LEN, TL ...) () {<br> =A0 =A0writefln(&quot;%s&quot;, is(TL[0 .. LEN] =3D=3D TL[LEN .. $]));<br> }<br><br></blockquote><div><br>Since to be equal, they must have the same l= ength, you can even get rid of the &#39;len&#39; part and cut in the middle= :<br><br>bool compare(TT...)() {<br>=A0=A0=A0 static if (TT.length % 2 =3D= =3D 0 &amp;&amp; is(TT[0..$/2] =3D=3D TT[$/2..$]))<br> =A0=A0=A0=A0=A0=A0=A0 return true;<br>=A0=A0=A0 else<br>=A0=A0=A0=A0=A0=A0= =A0 return false;<br>}<br><br>That&#39;s useful to compare two functions:<b= r><br>template sameArgs(alias fun1, alias fun2) {<br>=A0=A0=A0 static if (c= ompare!(ParameterTypeTuple!fun1, ParameterTypeTuple!fun2))<br> =A0=A0=A0=A0=A0=A0=A0 enum bool sameArgs =3D true;<br>=A0=A0=A0 else<br>=A0= =A0=A0=A0=A0=A0=A0 enum bool sameArgs =3D false;<br>}<br><br>(I think we co= uld use std.traits.Select to manage this kind of static ifs)<br><br>=A0 Phi= lippe<br><br></div></div> --00151743f7ce655aaa04837b21e5--
Apr 05 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0015174c14341b5e4f04837bf27a
Content-Type: text/plain; charset=ISO-8859-1

On Mon, Apr 5, 2010 at 12:52, Philippe Sigaud <philippe.sigaud gmail.com>wrote:


 That's useful to compare two functions:

 template sameArgs(alias fun1, alias fun2) {
     static if (compare!(ParameterTypeTuple!fun1, ParameterTypeTuple!fun2))

Ugh, forget this example, in this case we know the original tuples, so == is simpler and cleaner. Another interesting thing to test is if one typetuple can be converted into another. Maybe like this: bool compatibleTypeTuples(TT...) { TT[0..$/2] tt1; TT[$/2..$] tt2; static if (__traits(compiles, tt1 = tt2)) return true; else return false; } --0015174c14341b5e4f04837bf27a Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Mon, Apr 5, 2010 at 12:52, Philippe Sigaud <s= pan dir=3D"ltr">&lt;<a href=3D"mailto:philippe.sigaud gmail.com">philippe.s= igaud gmail.com</a>&gt;</span> wrote:<br><div>=A0</div><blockquote class=3D= "gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rg= b(204, 204, 204); padding-left: 1ex;"> <div class=3D"gmail_quote"><div>That&#39;s useful to compare two functions:= <br><br>template sameArgs(alias fun1, alias fun2) {<br>=A0=A0=A0 static if = (compare!(ParameterTypeTuple!fun1, ParameterTypeTuple!fun2))<br></div></div=
</blockquote>

, so =3D=3D is simpler and cleaner.<br><br>Another interesting thing to tes= t is if one typetuple can be converted into another.<br>Maybe like this:<br=

=A0 TT[$/2..$] tt2;<br>=A0 =A0 static if (__traits(compiles, tt1 =3D tt2))<= br>=A0 =A0 =A0 =A0 return true;<br>=A0 =A0 else<br>=A0 =A0 =A0 =A0 return f= alse;<br>}<br>=A0</div></div> --0015174c14341b5e4f04837bf27a--
Apr 05 2010
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--00032555b16a4a389604837c0af8
Content-Type: text/plain; charset=ISO-8859-1

On Mon, Apr 5, 2010 at 13:47, bearophile <bearophileHUGS lycos.com> wrote:

 Philippe Sigaud:
 Since to be equal, they must have the same length, you can even get rid

 the 'len' part and cut in the middle:

But if their length is not equal that can cause bugs.

that (int,int) and (double, int, int, double) are equal. Doh, I'll go and find some chocolate to go with my cappuccino. Philippe --00032555b16a4a389604837c0af8 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Mon, Apr 5, 2010 at 13:47, bearophile= <span dir=3D"ltr">&lt;<a href=3D"mailto:bearophileHUGS lycos.com">bearophi= leHUGS lycos.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, 2= 04); padding-left: 1ex;"> Philippe Sigaud:<br> <div class=3D"im">&gt; Since to be equal, they must have the same length, y= ou can even get rid of<br> &gt; the &#39;len&#39; part and cut in the middle:<br> <br> </div>But if their length is not equal that can cause bugs.<br><br></blockq= uote><div><br>Uh, next time I&#39;ll try to eat before posting. Indeed, my = template would say that (int,int) and (double, int, int, double) are equal.= <br> Doh, I&#39;ll go and find some chocolate to go with my cappuccino.<br><br>P= hilippe<br><br><br></div></div> --00032555b16a4a389604837c0af8--
Apr 05 2010