www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - TDPL: Overloading template functions

reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
There are two templated functions that overload against each other, and should
pass the unittests. But there are a few problems. Here's the example code:

T[] find(T, E)(T[] haystack, E needle) 
    if (is(typeof(haystack[0] != needle) == bool))
{
    while (haystack.length > 0 && haystack[0] != needle) {
        haystack = haystack[1 .. $];
    }
    return haystack;
}

T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (is(typeof(longer[0 .. 1] == shorter) : bool))
{
    while (longer.length >= shorter.length) {
        if (longer[0 .. shorter.length] == shorter)
            break;
        longer = longer[1 .. $];
    }
    return longer;
}

unittest {
    double[] d1 = [6.0, 1.5, 2.4, 3];
    float[] d2 = [1.5, 2.4];
    assert(find(d1, d2) == d1[1 .. $]);
}

unittest {
    double[] d = [1.5, 2.4];
    assert(find(d, 1.0) == null);
    assert(find(d, 1.5) == d);
    
    string[] s = ["one", "two"];
    assert(find(s, "two") == ["two"]);
}

The first unittest will fail. There is some funky issue going around here. This
small code will pass the unittest:

import std.stdio;

void main() {
}

float x = 4.0;
double y = 4.0;

unittest {
    assert(x == y);
}

But this one will not:

import std.stdio;

void main() {
}

float x = 4.2;
double y = 4.2;

unittest {
    assert(x == y);
}

Notice I've only changed the 0's to a different number. So, if I change the
first unittest in the original code to this:

unittest {
    double[] d1 = [6.0, 1.0, 2.0, 3];
    float[] d2 = [1.0, 2.0];
    assert(find(d1, d2) == d1[1 .. $]);
}

It will pass. I guess this has something to do with internal representation of
floats/doubles..

The second unittest from the Example code, which I'm pasting here again for
convenience:

unittest {
    double[] d = [1.5, 2.4];
    assert(find(d, 1.0) == null);
    assert(find(d, 1.5) == d);
    
    string[] s = ["one", "two"];
    assert(find(s, "two") == ["two"]);
}

Gives a compiler error saying that both of the overloaded templated functions
match for the call (the last assert in the unittest).

Also, Andrei, you never explained the if(is()) signature of the second
templated function. I hope to get some pointers on that. :)
Jul 27 2010
next sibling parent reply Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0015173ff38ed4cdcc048c73a6f2
Content-Type: text/plain; charset=ISO-8859-1

On Wed, Jul 28, 2010 at 05:50, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

I won't comment on the double/float issue, I do not anything about it.


 T[] find(T, E)(T[] haystack, E needle)
    if (is(typeof(haystack[0] != needle) == bool))

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (is(typeof(longer[0 .. 1] == shorter) : bool))

 Also, Andrei, you never explained the if(is()) signature of the second
 templated function. I hope to get some pointers on that. :)

I'll have a try at this one. As you may know, the is(typeof()) syntax is a way to try to compile an expression and see if it works. If it works, it has a type, given by typeof and is(Type) returns true. So the first one is really saying: "Hey compiler, may I compare an element of haystack (of type T) with an E In this case, longer is an array. So longer[0] would be an element, a T1. There is no chance that shorter will match as an element cannot be equal to an array ... except, of course, if longer is an array of T2[] (T1 == T2[]). Longer is a T2[][]. That may happen for arrays of strings, strings being arrays of chars. And I think that's the problem you have in your last unit test. Anyway, he takes longer[0..1] to get a slice, which is a dynamic array, a T1[] and hence comparable to a T2[]... most of the time. As for using ': bool' instead of '== bool' as in the first find(), I don't think there is any difference in this case. I understand T == U as 'T is the exact same type as U', whereas T : U is for me "T is a subtype of U". But then, a subtype of bool is pretty much constrained to be a bool. The T : U syntax is pretty much only used for classes : if(is(T : MyClass)) is saying : 'compile this only if T is a subclass of MyClass'. Philippe , except if longer is in fact --0015173ff38ed4cdcc048c73a6f2 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 05:50, Andrej Mitrovic <= span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andrej.m= itrovich gmail.com</a>&gt;</span> wrote:<br><div><br></div><div>I won&#39;t= comment on the double/float issue, I do not anything about it.</div> <div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;= border-left:1px #ccc solid;padding-left:1ex;">T[] find(T, E)(T[] haystack, = E needle)<br> =A0 =A0if (is(typeof(haystack[0] !=3D needle) =3D=3D bool))<br><br> T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br> =A0 =A0if (is(typeof(longer[0 .. 1] =3D=3D shorter) : bool))<br><br> Also, Andrei, you never explained the if(is()) signature of the second temp= lated function. I hope to get some pointers on that. :)<br> </blockquote></div><div><br></div>I&#39;ll have a try at this one.<div>As y= ou may know, the is(typeof()) syntax is a way to try to compile an expressi= on and see if it works. If it works, it has a type, given by typeof and is(= Type) returns true. So the first one is really saying: &quot;Hey compiler, = may I compare an element of haystack (of type T) with an E</div> <div>In this case,=A0longer is an array. So longer[0] would be an element, = a T1. There is no chance that shorter will match as an element cannot be eq= ual to an array ... except, of course, if longer is an array of T2[] =A0(T1= =3D=3D T2[]). Longer is a T2[][]. That may happen for arrays of strings, s= trings being arrays of chars. And I think that&#39;s the problem you have i= n your last unit test.<div> <br></div><div>Anyway,=A0he takes longer[0..1] to get a slice, which is a d= ynamic array, a T1[] and hence comparable to a T2[]... most of the time.</d= iv><div><br></div><div>As for using &#39;: bool&#39; instead of &#39;=3D=3D= bool&#39; as in the first find(), =A0I don&#39;t think there is any differ= ence in this case. I understand T =3D=3D U as &#39;T is the exact same type= as U&#39;, whereas T : U is for me &quot;T is a subtype of U&quot;. But th= en, a subtype of bool is pretty much constrained to be a bool. The T : U sy= ntax is pretty much only used for classes : if(is(T : MyClass)) is saying := &#39;compile this only if T is a subclass of MyClass&#39;.</div> <div><br></div><div><br></div><div>Philippe</div><div><br></div><div><br></= div><div><br></div><div>, except if longer is in fact</div></div> --0015173ff38ed4cdcc048c73a6f2--
Jul 28 2010
parent Ryan W Sims <rwsims gmail.com> writes:
On 7/28/10 7:44 AM, Philippe Sigaud wrote:
 On Wed, Jul 28, 2010 at 05:50, Andrej Mitrovic
 <andrej.mitrovich gmail.com <mailto:andrej.mitrovich gmail.com>> wrote:

 I won't comment on the double/float issue, I do not anything about it.

     T[] find(T, E)(T[] haystack, E needle)
         if (is(typeof(haystack[0] != needle) == bool))

     T1[] find(T1, T2)(T1[] longer, T2[] shorter)
         if (is(typeof(longer[0 .. 1] == shorter) : bool))

     Also, Andrei, you never explained the if(is()) signature of the
     second templated function. I hope to get some pointers on that. :)

If I understand the 'is' statement correctly, wouldn't this be a little less verbose and still the same semantics? T[] find(T, E)(T[] haystack, E needle) if (is(typeof(haystack[0] != needle)) { ...do the find... } (i.e. just drop the "== bool" from the guard?) When I compiled it, assert(find([1.0, 2.0], 2) == [2.0]) compiled fine, and assert(find([1, 2], "2") == []) didn't which is expected. Is there something I'm missing? -- rwsims
 I'll have a try at this one.
 As you may know, the is(typeof()) syntax is a way to try to compile an
 expression and see if it works. If it works, it has a type, given by
 typeof and is(Type) returns true. So the first one is really saying:
 "Hey compiler, may I compare an element of haystack (of type T) with an E
 In this case, longer is an array. So longer[0] would be an element, a
 T1. There is no chance that shorter will match as an element cannot be
 equal to an array ... except, of course, if longer is an array of T2[]
   (T1 == T2[]). Longer is a T2[][]. That may happen for arrays of
 strings, strings being arrays of chars. And I think that's the problem
 you have in your last unit test.

 Anyway, he takes longer[0..1] to get a slice, which is a dynamic array,
 a T1[] and hence comparable to a T2[]... most of the time.

 As for using ': bool' instead of '== bool' as in the first find(),  I
 don't think there is any difference in this case. I understand T == U as
 'T is the exact same type as U', whereas T : U is for me "T is a subtype
 of U". But then, a subtype of bool is pretty much constrained to be a
 bool. The T : U syntax is pretty much only used for classes : if(is(T :
 MyClass)) is saying : 'compile this only if T is a subclass of MyClass'.


 Philippe



 , except if longer is in fact

Aug 01 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016367fb52909ddcf048c7431f9
Content-Type: text/plain; charset=ISO-8859-1

These templates seem to be hard to get right. I guess with experience they
get easier to write and comprehend. Anyways, thanks for the explanation.

On Wed, Jul 28, 2010 at 4:44 PM, Philippe Sigaud
<philippe.sigaud gmail.com>wrote:

 On Wed, Jul 28, 2010 at 05:50, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

I won't comment on the double/float issue, I do not anything about it.
 T[] find(T, E)(T[] haystack, E needle)
    if (is(typeof(haystack[0] != needle) == bool))

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (is(typeof(longer[0 .. 1] == shorter) : bool))

 Also, Andrei, you never explained the if(is()) signature of the second
 templated function. I hope to get some pointers on that. :)

I'll have a try at this one. As you may know, the is(typeof()) syntax is a way to try to compile an expression and see if it works. If it works, it has a type, given by typeof and is(Type) returns true. So the first one is really saying: "Hey compiler, may I compare an element of haystack (of type T) with an E In this case, longer is an array. So longer[0] would be an element, a T1. There is no chance that shorter will match as an element cannot be equal to an array ... except, of course, if longer is an array of T2[] (T1 == T2[]). Longer is a T2[][]. That may happen for arrays of strings, strings being arrays of chars. And I think that's the problem you have in your last unit test. Anyway, he takes longer[0..1] to get a slice, which is a dynamic array, a T1[] and hence comparable to a T2[]... most of the time. As for using ': bool' instead of '== bool' as in the first find(), I don't think there is any difference in this case. I understand T == U as 'T is the exact same type as U', whereas T : U is for me "T is a subtype of U". But then, a subtype of bool is pretty much constrained to be a bool. The T : U syntax is pretty much only used for classes : if(is(T : MyClass)) is saying : 'compile this only if T is a subclass of MyClass'. Philippe , except if longer is in fact

--0016367fb52909ddcf048c7431f9 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable These templates seem to be hard to get right. I guess with experience they = get easier to write and comprehend. Anyways, thanks for the explanation.<br=
<br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 4:44 PM, Philippe S=

ilippe.sigaud gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class=3D"gma= il_quote">On Wed, Jul 28, 2010 at 05:50, Andrej Mitrovic <span dir=3D"ltr">= &lt;<a href=3D"mailto:andrej.mitrovich gmail.com" target=3D"_blank">andrej.= mitrovich gmail.com</a>&gt;</span> wrote:<br> <div><br></div><div>I won&#39;t comment on the double/float issue, I do not= anything about it.</div> <div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0p= t 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><di= v class=3D"im">T[] find(T, E)(T[] haystack, E needle)<br> =A0 =A0if (is(typeof(haystack[0] !=3D needle) =3D=3D bool))<br><br></div><= div class=3D"im"> T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br> =A0 =A0if (is(typeof(longer[0 .. 1] =3D=3D shorter) : bool))<br><br></div>= <div class=3D"im"> Also, Andrei, you never explained the if(is()) signature of the second temp= lated function. I hope to get some pointers on that. :)<br> </div></blockquote></div><div><br></div>I&#39;ll have a try at this one.<di= v>As you may know, the is(typeof()) syntax is a way to try to compile an ex= pression and see if it works. If it works, it has a type, given by typeof a= nd is(Type) returns true. So the first one is really saying: &quot;Hey comp= iler, may I compare an element of haystack (of type T) with an E</div> <div>In this case,=A0longer is an array. So longer[0] would be an element, = a T1. There is no chance that shorter will match as an element cannot be eq= ual to an array ... except, of course, if longer is an array of T2[] =A0(T1= =3D=3D T2[]). Longer is a T2[][]. That may happen for arrays of strings, s= trings being arrays of chars. And I think that&#39;s the problem you have i= n your last unit test.<div> <br></div><div>Anyway,=A0he takes longer[0..1] to get a slice, which is a d= ynamic array, a T1[] and hence comparable to a T2[]... most of the time.</d= iv><div><br></div><div>As for using &#39;: bool&#39; instead of &#39;=3D=3D= bool&#39; as in the first find(), =A0I don&#39;t think there is any differ= ence in this case. I understand T =3D=3D U as &#39;T is the exact same type= as U&#39;, whereas T : U is for me &quot;T is a subtype of U&quot;. But th= en, a subtype of bool is pretty much constrained to be a bool. The T : U sy= ntax is pretty much only used for classes : if(is(T : MyClass)) is saying := &#39;compile this only if T is a subclass of MyClass&#39;.</div> <div><br></div><div><br></div><div>Philippe</div><div><br></div><div><br></= div><div><br></div><div>, except if longer is in fact</div></div> </blockquote></div><br> --0016367fb52909ddcf048c7431f9--
Jul 28 2010
prev sibling next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Andrej Mitrovic wrote:
 Also, Andrei, you never explained the if(is()) signature of the second
templated function. I hope to get some pointers on that. :)

Is the explanation on page 141 adequate? Andrei
Jul 28 2010
next sibling parent Jonathan M Davis <jmdavisprog gmail.com> writes:
On Wednesday, July 28, 2010 09:49:52 Andrej Mitrovic wrote:
 IIRC arrays are value types and as such they are compared bit-by-bit
 to each other, right?

Dynamic arrays are reference types (though static arrays are indeed value types), and they evaluate for equality by comparing each element in turn (though presumably, they compare their length first and don't bother with element comparisons if the lengths don't match). Look at section 4.1.5 on page 100 of TDPL. - Jonathan M Davis
Jul 28 2010
prev sibling next sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016365eea0847a018048c75ffca
Content-Type: text/plain; charset=ISO-8859-1

Woops, I got confused. I was thinking about structs, not arrays.

But yeah, in this case a float gets compared to a double and it seems to
evaluate to false.

On Wed, Jul 28, 2010 at 7:26 PM, Jonathan M Davis <jmdavisprog gmail.com>wrote:

 On Wednesday, July 28, 2010 09:49:52 Andrej Mitrovic wrote:
 IIRC arrays are value types and as such they are compared bit-by-bit
 to each other, right?

Dynamic arrays are reference types (though static arrays are indeed value types), and they evaluate for equality by comparing each element in turn (though presumably, they compare their length first and don't bother with element comparisons if the lengths don't match). Look at section 4.1.5 on page 100 of TDPL. - Jonathan M Davis

--0016365eea0847a018048c75ffca Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Woops, I got confused. I was thinking about structs, not arrays. <br><br>Bu= t yeah, in this case a float gets compared to a double and it seems to eval= uate to false.<br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 7:= 26 PM, Jonathan M Davis <span dir=3D"ltr">&lt;<a href=3D"mailto:jmdavisprog= gmail.com">jmdavisprog gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class=3D"im"=
On Wednesday, July 28, 2010 09:49:52 Andrej Mitrovic wrote:<br>

r> &gt; to each other, right?<br> <br> </div>Dynamic arrays are reference types (though static arrays are indeed v= alue<br> types), and they evaluate for equality by comparing each element in turn (t= hough<br> presumably, they compare their length first and don&#39;t bother with eleme= nt<br> comparisons if the lengths don&#39;t match). Look at section 4.1.5 on page = 100 of<br> TDPL.<br> <font color=3D"#888888"><br> - Jonathan M Davis<br> </font></blockquote></div><br> --0016365eea0847a018048c75ffca--
Jul 28 2010
parent Rainer Schuetze <r.sagitario gmx.de> writes:
Andrej Mitrovic wrote:
 Woops, I got confused. I was thinking about structs, not arrays.
 
 But yeah, in this case a float gets compared to a double and it seems to 
 evaluate to false.

2.4 has no exact representation as a floating point value, as it is 2^^2*0.6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after 53 bits for a double. As a result float f = 2.4; // approximately 2.4000001 double d = 2.4; // approximately 2.3999999999999999 assert(f == d); fails, because the comparison is done after converting the truncated float to double (as long as the compiler does not issue SSE instructions with single precision). In contrast, this assert(2.4 == 2.4f); passes, as the compiler keeps real precision until writing the value to memory and evaluates the expression at compile time.
Jul 28 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016364d233520370b048c78af0f
Content-Type: text/plain; charset=ISO-8859-1

On page 143 there's a new find() overloaded function which is more
specialized than the last generic function, but I'm still getting an
ambiguity error. Although the book doesn't state if that specific unittest
should work, so I'm left wondering :) Here's the code:

void main()
{
}

T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (is(typeof(longer[0 .. 1] == shorter) : bool))
{
    while (longer.length >= shorter.length) {
        if (longer[0 .. shorter.length] == shorter)
            break;
        longer = longer[1 .. $];
    }
    return longer;
}

int[] find(int[] longer, int[] shorter) { }

unittest {
    int[] ints1 = [1, 2, 3, 5, 2] ;
    int[] ints2 = [3, 5];
    auto test = find(ints1, ints2);
}

test.d(16): Error: function test.find conflicts with template
test.find(T1,T2) if (is(typeof(longer[0..1] == shorter) : bool)) at
test.d(5)


And on page 145 the last example is:

void main() { }

void transmogrify(uint) { }
void transmogrify(long) { }
void transmogrify(T)(T value) { }

unittest {
    transmogrify(42);
    transmogrify("hello");
    transmogrify(1.1);
}

test2.d(5): Error: template test2.transmogrify(T) conflicts with function
test2.transmogrify at test2.d(3)

On Wed, Jul 28, 2010 at 7:32 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 Woops, I got confused. I was thinking about structs, not arrays.

 But yeah, in this case a float gets compared to a double and it seems to
 evaluate to false.


 On Wed, Jul 28, 2010 at 7:26 PM, Jonathan M Davis <jmdavisprog gmail.com>wrote:

 On Wednesday, July 28, 2010 09:49:52 Andrej Mitrovic wrote:
 IIRC arrays are value types and as such they are compared bit-by-bit
 to each other, right?

Dynamic arrays are reference types (though static arrays are indeed value types), and they evaluate for equality by comparing each element in turn (though presumably, they compare their length first and don't bother with element comparisons if the lengths don't match). Look at section 4.1.5 on page 100 of TDPL. - Jonathan M Davis


--0016364d233520370b048c78af0f Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable On page 143 there&#39;s a new find() overloaded function which is more spec= ialized than the last generic function, but I&#39;m still getting an ambigu= ity error. Although the book doesn&#39;t state if that specific unittest sh= ould work, so I&#39;m left wondering :) Here&#39;s the code:<br> <br>void main()<br>{<br>}<br><br>T1[] find(T1, T2)(T1[] longer, T2[] shorte= r)<br>=A0=A0=A0 if (is(typeof(longer[0 .. 1] =3D=3D shorter) : bool))<br>{<= br>=A0=A0=A0 while (longer.length &gt;=3D shorter.length) {<br>=A0=A0=A0=A0= =A0=A0=A0 if (longer[0 .. shorter.length] =3D=3D shorter)<br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 longer = =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br>}<br><br>= int[] find(int[] longer, int[] shorter) { }<br><br>unittest {<br>=A0=A0=A0 = int[] ints1 =3D [1, 2, 3, 5, 2] ;<br>=A0=A0=A0 int[] ints2 =3D [3, 5];<br> =A0=A0=A0 auto test =3D find(ints1, ints2);<br>}<br><br>test.d(16): Error: = function test.find conflicts with template test.find(T1,T2) if (is(typeof(l= onger[0..1] =3D=3D shorter) : bool)) at test.d(5)<br><br><br>And on page 14= 5 the last example is:<br> <br>void main() { }<br><br>void transmogrify(uint) { }<br>void transmogrify= (long) { }<br>void transmogrify(T)(T value) { }<br><br>unittest {<br>=A0=A0= =A0 transmogrify(42);<br>=A0=A0=A0 transmogrify(&quot;hello&quot;);<br>=A0= =A0=A0 transmogrify(1.1);<br> }<br><br>test2.d(5): Error: template test2.transmogrify(T) conflicts with f= unction test2.transmogrify at test2.d(3)<br><br><div class=3D"gmail_quote">= On Wed, Jul 28, 2010 at 7:32 PM, Andrej Mitrovic <span dir=3D"ltr">&lt;<a h= ref=3D"mailto:andrej.mitrovich gmail.com">andrej.mitrovich gmail.com</a>&gt= ;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Woops, I got conf= used. I was thinking about structs, not arrays. <br><br>But yeah, in this c= ase a float gets compared to a double and it seems to evaluate to false.<di= v> <div></div><div class=3D"h5"><br><br><div class=3D"gmail_quote">On Wed, Jul= 28, 2010 at 7:26 PM, Jonathan M Davis <span dir=3D"ltr">&lt;<a href=3D"mai= lto:jmdavisprog gmail.com" target=3D"_blank">jmdavisprog gmail.com</a>&gt;<= /span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>On Wednesday= , July 28, 2010 09:49:52 Andrej Mitrovic wrote:<br> &gt; IIRC arrays are value types and as such they are compared bit-by-bit<b= r> &gt; to each other, right?<br> <br> </div>Dynamic arrays are reference types (though static arrays are indeed v= alue<br> types), and they evaluate for equality by comparing each element in turn (t= hough<br> presumably, they compare their length first and don&#39;t bother with eleme= nt<br> comparisons if the lengths don&#39;t match). Look at section 4.1.5 on page = 100 of<br> TDPL.<br> <font color=3D"#888888"><br> - Jonathan M Davis<br> </font></blockquote></div><br> </div></div></blockquote></div><br> --0016364d233520370b048c78af0f--
Jul 28 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--001636498f310e299c048c78edcf
Content-Type: text/plain; charset=ISO-8859-1

Page 149, the two shorter-hand ways of writing function literals are not
working for me:

void main() { }

T[] find(alias pred, T)(T[] input)
    if (is(typeof(pred(input[0])) == bool))
{
    for (; input.length > 0; input = input[1 .. $]) {
        if (pred(input[0]))
            break;
    }
    return input;
}

unittest {
    int[] a = [1, 2, 3, 4, -5, 3, -4];

    auto b = find!(function bool(int x) { return x < 0; })(a);
    //~ auto c = find!(function(x) { return x < 0; })(a);
    //~ auto d = find!((x) { return x < 0; })(a);
}

The first one works fine. But if I uncomment the second or third line I get
these errors:

higher_order_functions.d(17): Error: template
higher_order_functions.find(alias pred,T) if (is(typeof(pred(input[0])) ==
bool)) does not match any function template declaration

higher_order_functions.d(17): Error: template
higher_order_functions.find(alias pred,T) if (is(typeof(pred(input[0])) ==
bool)) cannot deduce template function from argument types
!(__funcliteral1)(int[])


On Wed, Jul 28, 2010 at 10:44 PM, Andrej Mitrovic <
andrej.mitrovich gmail.com> wrote:

 On page 143 there's a new find() overloaded function which is more
 specialized than the last generic function, but I'm still getting an
 ambiguity error. Although the book doesn't state if that specific unittest
 should work, so I'm left wondering :) Here's the code:

 void main()

 {
 }

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
     if (is(typeof(longer[0 .. 1] == shorter) : bool))
 {
     while (longer.length >= shorter.length) {
         if (longer[0 .. shorter.length] == shorter)
             break;
         longer = longer[1 .. $];
     }
     return longer;
 }

 int[] find(int[] longer, int[] shorter) { }

 unittest {
     int[] ints1 = [1, 2, 3, 5, 2] ;
     int[] ints2 = [3, 5];
     auto test = find(ints1, ints2);
 }

 test.d(16): Error: function test.find conflicts with template
 test.find(T1,T2) if (is(typeof(longer[0..1] == shorter) : bool)) at
 test.d(5)


 And on page 145 the last example is:

 void main() { }

 void transmogrify(uint) { }
 void transmogrify(long) { }
 void transmogrify(T)(T value) { }

 unittest {
     transmogrify(42);
     transmogrify("hello");
     transmogrify(1.1);
 }

 test2.d(5): Error: template test2.transmogrify(T) conflicts with function
 test2.transmogrify at test2.d(3)


 On Wed, Jul 28, 2010 at 7:32 PM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 Woops, I got confused. I was thinking about structs, not arrays.

 But yeah, in this case a float gets compared to a double and it seems to
 evaluate to false.


 On Wed, Jul 28, 2010 at 7:26 PM, Jonathan M Davis <jmdavisprog gmail.com>wrote:

 On Wednesday, July 28, 2010 09:49:52 Andrej Mitrovic wrote:
 IIRC arrays are value types and as such they are compared bit-by-bit
 to each other, right?

Dynamic arrays are reference types (though static arrays are indeed value types), and they evaluate for equality by comparing each element in turn (though presumably, they compare their length first and don't bother with element comparisons if the lengths don't match). Look at section 4.1.5 on page 100 of TDPL. - Jonathan M Davis



--001636498f310e299c048c78edcf Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Page 149, the two shorter-hand ways of writing function literals are not wo= rking for me:<br><br>void main() { }<br><br>T[] find(alias pred, T)(T[] inp= ut)<br>=A0=A0=A0 if (is(typeof(pred(input[0])) =3D=3D bool))<br>{<br>=A0=A0= =A0 for (; input.length &gt; 0; input =3D input[1 .. $]) {<br> =A0=A0=A0=A0=A0=A0=A0 if (pred(input[0]))<br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 break;<br>=A0=A0=A0 }<br>=A0=A0=A0 return input;<br>}<br><br>unittest {= <br>=A0=A0=A0 int[] a =3D [1, 2, 3, 4, -5, 3, -4];<br>=A0=A0=A0 <br>=A0=A0= =A0 auto b =3D find!(function bool(int x) { return x &lt; 0; })(a);<br> =A0=A0=A0 //~ auto c =3D find!(function(x) { return x &lt; 0; })(a);<br>=A0= =A0=A0 //~ auto d =3D find!((x) { return x &lt; 0; })(a);<br>}<br><br>The f= irst one works fine. But if I uncomment the second or third line I get thes= e errors:<br> <br>higher_order_functions.d(17): Error: template higher_order_functions.fi= nd(alias pred,T) if (is(typeof(pred(input[0])) =3D=3D bool)) does not match= any function template declaration<br><br>higher_order_functions.d(17): Err= or: template higher_order_functions.find(alias pred,T) if (is(typeof(pred(i= nput[0])) =3D=3D bool)) cannot deduce template function from argument types= !(__funcliteral1)(int[])<br> <br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 10:44 PM, Andrej= Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.co= m">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><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;"> On page 143 there&#39;s a new find() overloaded function which is more spec= ialized than the last generic function, but I&#39;m still getting an ambigu= ity error. Although the book doesn&#39;t state if that specific unittest sh= ould work, so I&#39;m left wondering :) Here&#39;s the code:<br> <br>void main()<div class=3D"im"><br>{<br>}<br><br>T1[] find(T1, T2)(T1[] l= onger, T2[] shorter)<br>=A0=A0=A0 if (is(typeof(longer[0 .. 1] =3D=3D short= er) : bool))<br>{<br>=A0=A0=A0 while (longer.length &gt;=3D shorter.length)= {<br>=A0=A0=A0=A0=A0=A0=A0 if (longer[0 .. shorter.length] =3D=3D shorter)= <br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 longer = =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br>}<br><br>= </div>int[] find(int[] longer, int[] shorter) { }<br><br>unittest {<br>=A0= =A0=A0 int[] ints1 =3D [1, 2, 3, 5, 2] ;<br>=A0=A0=A0 int[] ints2 =3D [3, 5= ];<br> =A0=A0=A0 auto test =3D find(ints1, ints2);<br>}<br><br>test.d(16): Error: = function test.find conflicts with template test.find(T1,T2) if (is(typeof(l= onger[0..1] =3D=3D shorter) : bool)) at test.d(5)<br><br><br>And on page 14= 5 the last example is:<br> <br>void main() { }<br><br>void transmogrify(uint) { }<br>void transmogrify= (long) { }<br>void transmogrify(T)(T value) { }<br><br>unittest {<br>=A0=A0= =A0 transmogrify(42);<br>=A0=A0=A0 transmogrify(&quot;hello&quot;);<br>=A0= =A0=A0 transmogrify(1.1);<br> }<br><br>test2.d(5): Error: template test2.transmogrify(T) conflicts with f= unction test2.transmogrify at test2.d(3)<div><div></div><div class=3D"h5"><= br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 7:32 PM, Andrej M= itrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com"= target=3D"_blank">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Woops, I got conf= used. I was thinking about structs, not arrays. <br><br>But yeah, in this c= ase a float gets compared to a double and it seems to evaluate to false.<di= v> <div></div><div><br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at = 7:26 PM, Jonathan M Davis <span dir=3D"ltr">&lt;<a href=3D"mailto:jmdavispr= og gmail.com" target=3D"_blank">jmdavisprog gmail.com</a>&gt;</span> wrote:= <br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>On Wednesday= , July 28, 2010 09:49:52 Andrej Mitrovic wrote:<br> &gt; IIRC arrays are value types and as such they are compared bit-by-bit<b= r> &gt; to each other, right?<br> <br> </div>Dynamic arrays are reference types (though static arrays are indeed v= alue<br> types), and they evaluate for equality by comparing each element in turn (t= hough<br> presumably, they compare their length first and don&#39;t bother with eleme= nt<br> comparisons if the lengths don&#39;t match). Look at section 4.1.5 on page = 100 of<br> TDPL.<br> <font color=3D"#888888"><br> - Jonathan M Davis<br> </font></blockquote></div><br> </div></div></blockquote></div><br> </div></div></blockquote></div><br> --001636498f310e299c048c78edcf--
Jul 28 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--001636498f31083fa8048c78fb83
Content-Type: text/plain; charset=ISO-8859-1

They do work if I specify the type before x, as in:
    auto c = find!(function(int x) { return x < 0; })(a);
    auto d = find!((int x) { return x < 0; })(a);


On Wed, Jul 28, 2010 at 11:01 PM, Andrej Mitrovic <
andrej.mitrovich gmail.com> wrote:

 Page 149, the two shorter-hand ways of writing function literals are not
 working for me:

 void main() { }

 T[] find(alias pred, T)(T[] input)
     if (is(typeof(pred(input[0])) == bool))
 {
     for (; input.length > 0; input = input[1 .. $]) {
         if (pred(input[0]))
             break;
     }
     return input;
 }

 unittest {
     int[] a = [1, 2, 3, 4, -5, 3, -4];

     auto b = find!(function bool(int x) { return x < 0; })(a);
     //~ auto c = find!(function(x) { return x < 0; })(a);
     //~ auto d = find!((x) { return x < 0; })(a);
 }

 The first one works fine. But if I uncomment the second or third line I get
 these errors:

 higher_order_functions.d(17): Error: template
 higher_order_functions.find(alias pred,T) if (is(typeof(pred(input[0])) ==
 bool)) does not match any function template declaration

 higher_order_functions.d(17): Error: template
 higher_order_functions.find(alias pred,T) if (is(typeof(pred(input[0])) ==
 bool)) cannot deduce template function from argument types
 !(__funcliteral1)(int[])



 On Wed, Jul 28, 2010 at 10:44 PM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 On page 143 there's a new find() overloaded function which is more
 specialized than the last generic function, but I'm still getting an
 ambiguity error. Although the book doesn't state if that specific unittest
 should work, so I'm left wondering :) Here's the code:

 void main()

 {
 }

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
     if (is(typeof(longer[0 .. 1] == shorter) : bool))
 {
     while (longer.length >= shorter.length) {
         if (longer[0 .. shorter.length] == shorter)
             break;
         longer = longer[1 .. $];
     }
     return longer;
 }

 int[] find(int[] longer, int[] shorter) { }

 unittest {
     int[] ints1 = [1, 2, 3, 5, 2] ;
     int[] ints2 = [3, 5];
     auto test = find(ints1, ints2);
 }

 test.d(16): Error: function test.find conflicts with template
 test.find(T1,T2) if (is(typeof(longer[0..1] == shorter) : bool)) at
 test.d(5)


 And on page 145 the last example is:

 void main() { }

 void transmogrify(uint) { }
 void transmogrify(long) { }
 void transmogrify(T)(T value) { }

 unittest {
     transmogrify(42);
     transmogrify("hello");
     transmogrify(1.1);
 }

 test2.d(5): Error: template test2.transmogrify(T) conflicts with function
 test2.transmogrify at test2.d(3)


 On Wed, Jul 28, 2010 at 7:32 PM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 Woops, I got confused. I was thinking about structs, not arrays.

 But yeah, in this case a float gets compared to a double and it seems to
 evaluate to false.


 On Wed, Jul 28, 2010 at 7:26 PM, Jonathan M Davis <jmdavisprog gmail.com
 wrote:

 On Wednesday, July 28, 2010 09:49:52 Andrej Mitrovic wrote:
 IIRC arrays are value types and as such they are compared bit-by-bit
 to each other, right?

Dynamic arrays are reference types (though static arrays are indeed value types), and they evaluate for equality by comparing each element in turn (though presumably, they compare their length first and don't bother with element comparisons if the lengths don't match). Look at section 4.1.5 on page 100 of TDPL. - Jonathan M Davis




--001636498f31083fa8048c78fb83 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br>They do work if I specify the type before x, as in:<br>=A0=A0=A0 auto c= =3D find!(function(int x) { return x &lt; 0; })(a);<br>=A0=A0=A0 auto d = =3D find!((int x) { return x &lt; 0; })(a);<br><br><br><div class=3D"gmail_= quote">On Wed, Jul 28, 2010 at 11:01 PM, Andrej Mitrovic <span dir=3D"ltr">= &lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andrej.mitrovich gmail.co= m</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Page 149, the two= shorter-hand ways of writing function literals are not working for me:<br> <br>void main() { }<br><br>T[] find(alias pred, T)(T[] input)<br>=A0=A0=A0 = if (is(typeof(pred(input[0])) =3D=3D bool))<br>{<br>=A0=A0=A0 for (; input.= length &gt; 0; input =3D input[1 .. $]) {<br> =A0=A0=A0=A0=A0=A0=A0 if (pred(input[0]))<br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 break;<br>=A0=A0=A0 }<br>=A0=A0=A0 return input;<br>}<br><br>unittest {= <br>=A0=A0=A0 int[] a =3D [1, 2, 3, 4, -5, 3, -4];<br>=A0=A0=A0 <br>=A0=A0= =A0 auto b =3D find!(function bool(int x) { return x &lt; 0; })(a);<br> =A0=A0=A0 //~ auto c =3D find!(function(x) { return x &lt; 0; })(a);<br>=A0= =A0=A0 //~ auto d =3D find!((x) { return x &lt; 0; })(a);<br>}<br><br>The f= irst one works fine. But if I uncomment the second or third line I get thes= e errors:<br> <br>higher_order_functions.d(17): Error: template higher_order_functions.fi= nd(alias pred,T) if (is(typeof(pred(input[0])) =3D=3D bool)) does not match= any function template declaration<br><br>higher_order_functions.d(17): Err= or: template higher_order_functions.find(alias pred,T) if (is(typeof(pred(i= nput[0])) =3D=3D bool)) cannot deduce template function from argument types= !(__funcliteral1)(int[])<div> <div></div><div class=3D"h5"><br> <br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 10:44 PM, Andrej= Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.co= m" target=3D"_blank">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><b= lockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-= left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> On page 143 there&#39;s a new find() overloaded function which is more spec= ialized than the last generic function, but I&#39;m still getting an ambigu= ity error. Although the book doesn&#39;t state if that specific unittest sh= ould work, so I&#39;m left wondering :) Here&#39;s the code:<br> <br>void main()<div><br>{<br>}<br><br>T1[] find(T1, T2)(T1[] longer, T2[] s= horter)<br>=A0=A0=A0 if (is(typeof(longer[0 .. 1] =3D=3D shorter) : bool))<= br>{<br>=A0=A0=A0 while (longer.length &gt;=3D shorter.length) {<br>=A0=A0= =A0=A0=A0=A0=A0 if (longer[0 .. shorter.length] =3D=3D shorter)<br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 longer = =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br>}<br><br>= </div>int[] find(int[] longer, int[] shorter) { }<br><br>unittest {<br>=A0= =A0=A0 int[] ints1 =3D [1, 2, 3, 5, 2] ;<br>=A0=A0=A0 int[] ints2 =3D [3, 5= ];<br> =A0=A0=A0 auto test =3D find(ints1, ints2);<br>}<br><br>test.d(16): Error: = function test.find conflicts with template test.find(T1,T2) if (is(typeof(l= onger[0..1] =3D=3D shorter) : bool)) at test.d(5)<br><br><br>And on page 14= 5 the last example is:<br> <br>void main() { }<br><br>void transmogrify(uint) { }<br>void transmogrify= (long) { }<br>void transmogrify(T)(T value) { }<br><br>unittest {<br>=A0=A0= =A0 transmogrify(42);<br>=A0=A0=A0 transmogrify(&quot;hello&quot;);<br>=A0= =A0=A0 transmogrify(1.1);<br> }<br><br>test2.d(5): Error: template test2.transmogrify(T) conflicts with f= unction test2.transmogrify at test2.d(3)<div><div></div><div><br><br><div c= lass=3D"gmail_quote">On Wed, Jul 28, 2010 at 7:32 PM, Andrej Mitrovic <span= dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com" target=3D"_b= lank">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Woops, I got conf= used. I was thinking about structs, not arrays. <br><br>But yeah, in this c= ase a float gets compared to a double and it seems to evaluate to false.<di= v> <div></div><div><br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at = 7:26 PM, Jonathan M Davis <span dir=3D"ltr">&lt;<a href=3D"mailto:jmdavispr= og gmail.com" target=3D"_blank">jmdavisprog gmail.com</a>&gt;</span> wrote:= <br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>On Wednesday= , July 28, 2010 09:49:52 Andrej Mitrovic wrote:<br> &gt; IIRC arrays are value types and as such they are compared bit-by-bit<b= r> &gt; to each other, right?<br> <br> </div>Dynamic arrays are reference types (though static arrays are indeed v= alue<br> types), and they evaluate for equality by comparing each element in turn (t= hough<br> presumably, they compare their length first and don&#39;t bother with eleme= nt<br> comparisons if the lengths don&#39;t match). Look at section 4.1.5 on page = 100 of<br> TDPL.<br> <font color=3D"#888888"><br> - Jonathan M Davis<br> </font></blockquote></div><br> </div></div></blockquote></div><br> </div></div></blockquote></div><br> </div></div></blockquote></div><br> --001636498f31083fa8048c78fb83--
Jul 28 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016364c7521d6c54b048c791eb5
Content-Type: text/plain; charset=ISO-8859-1

Should I just keep posting my findings in this thread? I hate to make a new
thread for every problem I find..

Anyway, on Page 150, this code fails:

auto f = (int i) {};
assert(is(f == function));

I've checked via typeid(), and f is a delegate by default, not a function.
I've tested it both in a function's scope and in module scope, with the same
results.

On Wed, Jul 28, 2010 at 10:56 PM, Rainer Schuetze <r.sagitario gmx.de>wrote:

 Andrej Mitrovic wrote:

 Woops, I got confused. I was thinking about structs, not arrays.


 But yeah, in this case a float gets compared to a double and it seems to
 evaluate to false.

2.4 has no exact representation as a floating point value, as it is 2^^2*0.6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after 53 bits for a double. As a result float f = 2.4; // approximately 2.4000001 double d = 2.4; // approximately 2.3999999999999999 assert(f == d); fails, because the comparison is done after converting the truncated float to double (as long as the compiler does not issue SSE instructions with single precision). In contrast, this assert(2.4 == 2.4f); passes, as the compiler keeps real precision until writing the value to memory and evaluates the expression at compile time.

--0016364c7521d6c54b048c791eb5 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Should I just keep posting my findings in this thread? I hate to make a new= thread for every problem I find.. <br><br>Anyway, on Page 150, this code f= ails:<br><br>auto f =3D (int i) {};<br>assert(is(f =3D=3D function));<br><b= r>I&#39;ve checked via typeid(), and f is a delegate by default, not a func= tion. I&#39;ve tested it both in a function&#39;s scope and in module scope= , with the same results.<br> <br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 10:56 PM, Rainer Sch= uetze <span dir=3D"ltr">&lt;<a href=3D"mailto:r.sagitario gmx.de">r.sagitar= io gmx.de</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); p= adding-left: 1ex;"> <br> Andrej Mitrovic wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> Woops, I got confused. I was thinking about structs, not arrays.<div class= =3D"im"><br> <br> But yeah, in this case a float gets compared to a double and it seems to ev= aluate to false.<br> </div></blockquote> <br> 2.4 has no exact representation as a floating point value, as it is 2^^2*0.= 6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after= 53 bits for a double. As a result<br> <br> =A0 =A0 =A0 =A0float f =3D 2.4; // approximately 2.4000001<br> =A0 =A0 =A0 =A0double d =3D 2.4; // approximately 2.3999999999999999<br> =A0 =A0 =A0 =A0assert(f =3D=3D d);<br> <br> fails, because the comparison is done after converting the truncated float = to double (as long as the compiler does not issue SSE instructions with sin= gle precision).<br> <br> In contrast, this<br> <br> =A0 =A0 =A0 =A0assert(2.4 =3D=3D 2.4f);<br> <br> passes, as the compiler keeps real precision until writing the value to mem= ory and evaluates the expression at compile time.<br> </blockquote></div><br> --0016364c7521d6c54b048c791eb5--
Jul 28 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016e65a01829a0757048c7d5187
Content-Type: text/plain; charset=ISO-8859-1

I can't get the example on page 158 to compile, I've tried both versions of
reduce:

import std.stdio, std.range;

 property bool empty(T)(T[] a) { return a.length == 0; }
 property ref T front(T)(T[] a) { return a[0]; }
void popFront(T)(ref T[] a) { a = a[1 .. $]; }

V reduce(alias fun, V, R)(V x, R range)
    if (isInputRange!R && is(typeof(x = fun(x, range.front))))
{
    for (; !range.empty; range.popFront()) {
        x = fun(x, range.front);
    }
    return x;
}

unittest {
    int[] r = [10, 14, 3, 5, 23];

    // compute the sum of all elements
    int sum = reduce!((a, b) { return a + b; })(0, r);
    assert(sum == 55);

    // compute minimum
    int min = reduce!((a, b) { return a < b ? a : b; })(r[0], r);
    assert(min == 3);
}

void main() { }

Errors:
reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
(isInputRange!(R) && is(typeof(x = fun(x,range.front)))) does not match any
function template declaration

reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
(isInputRange!(R) && is(typeof(x = fun(x,range.front)))) cannot deduce
template function from argument types !(__dgliteral1)(int,int[])

reduce.d(31): Error: template instance errors instantiating template

If I comment out the template constraints (the if statements for either
version of reduce), the example will compile and the unittests will pass.

On Wed, Jul 28, 2010 at 11:15 PM, Andrej Mitrovic <
andrej.mitrovich gmail.com> wrote:

 Should I just keep posting my findings in this thread? I hate to make a new
 thread for every problem I find..

 Anyway, on Page 150, this code fails:

 auto f = (int i) {};
 assert(is(f == function));

 I've checked via typeid(), and f is a delegate by default, not a function.
 I've tested it both in a function's scope and in module scope, with the same
 results.


 On Wed, Jul 28, 2010 at 10:56 PM, Rainer Schuetze <r.sagitario gmx.de>wrote:

 Andrej Mitrovic wrote:

 Woops, I got confused. I was thinking about structs, not arrays.


 But yeah, in this case a float gets compared to a double and it seems to
 evaluate to false.

2.4 has no exact representation as a floating point value, as it is 2^^2*0.6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after 53 bits for a double. As a result float f = 2.4; // approximately 2.4000001 double d = 2.4; // approximately 2.3999999999999999 assert(f == d); fails, because the comparison is done after converting the truncated float to double (as long as the compiler does not issue SSE instructions with single precision). In contrast, this assert(2.4 == 2.4f); passes, as the compiler keeps real precision until writing the value to memory and evaluates the expression at compile time.


--0016e65a01829a0757048c7d5187 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable I can&#39;t get the example on page 158 to compile, I&#39;ve tried both ver= sions of reduce:<br><br>import std.stdio, std.range;<br><br> property bool = empty(T)(T[] a) { return a.length =3D=3D 0; }<br> property ref T front(T)(T= [] a) { return a[0]; }<br> void popFront(T)(ref T[] a) { a =3D a[1 .. $]; }<br><br>V reduce(alias fun,= V, R)(V x, R range)<br>=A0=A0=A0 if (isInputRange!R &amp;&amp; is(typeof(x= =3D fun(x, range.front))))<br>{<br>=A0=A0=A0 for (; !range.empty; range.po= pFront()) {<br> =A0=A0=A0=A0=A0=A0=A0 x =3D fun(x, range.front);<br>=A0=A0=A0 }<br>=A0=A0= =A0 return x;<br>}<br><br>unittest {<br>=A0=A0=A0 int[] r =3D [10, 14, 3, 5= , 23];<br>=A0=A0=A0 <br>=A0=A0=A0 // compute the sum of all elements<br>=A0= =A0=A0 int sum =3D reduce!((a, b) { return a + b; })(0, r);<br> =A0=A0=A0 assert(sum =3D=3D 55);<br>=A0=A0=A0 <br>=A0=A0=A0 // compute mini= mum<br>=A0=A0=A0 int min =3D reduce!((a, b) { return a &lt; b ? a : b; })(r= [0], r);<br>=A0=A0=A0 assert(min =3D=3D 3);<br>}<br><br>void main() { }<br>= <br>Errors:<br>reduce.d(31): Error: template reduce.reduce(alias fun,V,R) i= f (isInputRange!(R) &amp;&amp; is(typeof(x =3D fun(x,range.front)))) does n= ot match any function template declaration<br> <br>reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if (isInputR= ange!(R) &amp;&amp; is(typeof(x =3D fun(x,range.front)))) cannot deduce tem= plate function from argument types !(__dgliteral1)(int,int[])<br><br>reduce= .d(31): Error: template instance errors instantiating template<br> <br>If I comment out the template constraints (the if statements for either= version of reduce), the example will compile and the unittests will pass.<= br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 11:15 PM, Andrej = Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com= ">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Should I just kee= p posting my findings in this thread? I hate to make a new thread for every= problem I find.. <br> <br>Anyway, on Page 150, this code fails:<br><br>auto f =3D (int i) {};<br>= assert(is(f =3D=3D function));<br><br>I&#39;ve checked via typeid(), and f = is a delegate by default, not a function. I&#39;ve tested it both in a func= tion&#39;s scope and in module scope, with the same results.<div> <div></div><div class=3D"h5"><br> <br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 10:56 PM, Rainer Sch= uetze <span dir=3D"ltr">&lt;<a href=3D"mailto:r.sagitario gmx.de" target=3D= "_blank">r.sagitario gmx.de</a>&gt;</span> wrote:<br><blockquote class=3D"g= mail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(= 204, 204, 204); padding-left: 1ex;"> <br> Andrej Mitrovic wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> Woops, I got confused. I was thinking about structs, not arrays.<div><br> <br> But yeah, in this case a float gets compared to a double and it seems to ev= aluate to false.<br> </div></blockquote> <br> 2.4 has no exact representation as a floating point value, as it is 2^^2*0.= 6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after= 53 bits for a double. As a result<br> <br> =A0 =A0 =A0 =A0float f =3D 2.4; // approximately 2.4000001<br> =A0 =A0 =A0 =A0double d =3D 2.4; // approximately 2.3999999999999999<br> =A0 =A0 =A0 =A0assert(f =3D=3D d);<br> <br> fails, because the comparison is done after converting the truncated float = to double (as long as the compiler does not issue SSE instructions with sin= gle precision).<br> <br> In contrast, this<br> <br> =A0 =A0 =A0 =A0assert(2.4 =3D=3D 2.4f);<br> <br> passes, as the compiler keeps real precision until writing the value to mem= ory and evaluates the expression at compile time.<br> </blockquote></div><br> </div></div></blockquote></div><br> --0016e65a01829a0757048c7d5187--
Jul 28 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--002215b01d52d98d36048c881ab1
Content-Type: text/plain; charset=ISO-8859-1

Page 160, code:

import std.algorithm, std.range;

void main() {}

double average() { return 1.0; }
double average(double) { return 2.0; }

// computes average of a set of numbers, passable directly or via an array
double average(double[] values...) {
    if (values.empty) {
        throw new Exception("Average of zero elements in undefined");
    }
    return reduce!((a, b) { return a + b; })(0.0, values) / values.length;
}

unittest {
    average();
    average(2.5);
}


The book states this is an ambiguous call, but I can succesfully compile.

On Thu, Jul 29, 2010 at 4:16 AM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 I can't get the example on page 158 to compile, I've tried both versions of
 reduce:

 import std.stdio, std.range;

  property bool empty(T)(T[] a) { return a.length == 0; }
  property ref T front(T)(T[] a) { return a[0]; }
 void popFront(T)(ref T[] a) { a = a[1 .. $]; }

 V reduce(alias fun, V, R)(V x, R range)
     if (isInputRange!R && is(typeof(x = fun(x, range.front))))
 {
     for (; !range.empty; range.popFront()) {
         x = fun(x, range.front);
     }
     return x;
 }

 unittest {
     int[] r = [10, 14, 3, 5, 23];

     // compute the sum of all elements
     int sum = reduce!((a, b) { return a + b; })(0, r);
     assert(sum == 55);

     // compute minimum
     int min = reduce!((a, b) { return a < b ? a : b; })(r[0], r);
     assert(min == 3);
 }

 void main() { }

 Errors:
 reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
 (isInputRange!(R) && is(typeof(x = fun(x,range.front)))) does not match any
 function template declaration

 reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
 (isInputRange!(R) && is(typeof(x = fun(x,range.front)))) cannot deduce
 template function from argument types !(__dgliteral1)(int,int[])

 reduce.d(31): Error: template instance errors instantiating template

 If I comment out the template constraints (the if statements for either
 version of reduce), the example will compile and the unittests will pass.


 On Wed, Jul 28, 2010 at 11:15 PM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 Should I just keep posting my findings in this thread? I hate to make a
 new thread for every problem I find..

 Anyway, on Page 150, this code fails:

 auto f = (int i) {};
 assert(is(f == function));

 I've checked via typeid(), and f is a delegate by default, not a function.
 I've tested it both in a function's scope and in module scope, with the same
 results.


 On Wed, Jul 28, 2010 at 10:56 PM, Rainer Schuetze <r.sagitario gmx.de>wrote:

 Andrej Mitrovic wrote:

 Woops, I got confused. I was thinking about structs, not arrays.


 But yeah, in this case a float gets compared to a double and it seems to
 evaluate to false.

2.4 has no exact representation as a floating point value, as it is 2^^2*0.6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after 53 bits for a double. As a result float f = 2.4; // approximately 2.4000001 double d = 2.4; // approximately 2.3999999999999999 assert(f == d); fails, because the comparison is done after converting the truncated float to double (as long as the compiler does not issue SSE instructions with single precision). In contrast, this assert(2.4 == 2.4f); passes, as the compiler keeps real precision until writing the value to memory and evaluates the expression at compile time.



--002215b01d52d98d36048c881ab1 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Page 160, code:<br><br>import std.algorithm, std.range;<br><br>void main() = {}<br><br>double average() { return 1.0; }<br>double average(double) { retu= rn 2.0; }<br><br>// computes average of a set of numbers, passable directly= or via an array<br> double average(double[] values...) {<br>=A0=A0=A0 if (values.empty) {<br>= =A0=A0=A0=A0=A0=A0=A0 throw new Exception(&quot;Average of zero elements in= undefined&quot;);<br>=A0=A0=A0 }<br>=A0=A0=A0 return reduce!((a, b) { retu= rn a + b; })(0.0, values) / values.length;<br> }<br><br>unittest {<br>=A0=A0=A0 average();<br>=A0=A0=A0 average(2.5);<br>}= <br><br><br>The book states this is an ambiguous call, but I can succesfull= y compile.<br><br><div class=3D"gmail_quote">On Thu, Jul 29, 2010 at 4:16 A= M, Andrej Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich= gmail.com">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">I can&#39;t get t= he example on page 158 to compile, I&#39;ve tried both versions of reduce:<= br> <br>import std.stdio, std.range;<br><br> property bool empty(T)(T[] a) { re= turn a.length =3D=3D 0; }<br> property ref T front(T)(T[] a) { return a[0];= }<br> void popFront(T)(ref T[] a) { a =3D a[1 .. $]; }<br><br>V reduce(alias fun,= V, R)(V x, R range)<br>=A0=A0=A0 if (isInputRange!R &amp;&amp; is(typeof(x= =3D fun(x, range.front))))<br>{<br>=A0=A0=A0 for (; !range.empty; range.po= pFront()) {<br> =A0=A0=A0=A0=A0=A0=A0 x =3D fun(x, range.front);<br>=A0=A0=A0 }<br>=A0=A0= =A0 return x;<br>}<br><br>unittest {<br>=A0=A0=A0 int[] r =3D [10, 14, 3, 5= , 23];<br>=A0=A0=A0 <br>=A0=A0=A0 // compute the sum of all elements<br>=A0= =A0=A0 int sum =3D reduce!((a, b) { return a + b; })(0, r);<br> =A0=A0=A0 assert(sum =3D=3D 55);<br>=A0=A0=A0 <br>=A0=A0=A0 // compute mini= mum<br>=A0=A0=A0 int min =3D reduce!((a, b) { return a &lt; b ? a : b; })(r= [0], r);<br>=A0=A0=A0 assert(min =3D=3D 3);<br>}<br><br>void main() { }<br>= <br>Errors:<br>reduce.d(31): Error: template reduce.reduce(alias fun,V,R) i= f (isInputRange!(R) &amp;&amp; is(typeof(x =3D fun(x,range.front)))) does n= ot match any function template declaration<br> <br>reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if (isInputR= ange!(R) &amp;&amp; is(typeof(x =3D fun(x,range.front)))) cannot deduce tem= plate function from argument types !(__dgliteral1)(int,int[])<br><br>reduce= .d(31): Error: template instance errors instantiating template<br> <br>If I comment out the template constraints (the if statements for either= version of reduce), the example will compile and the unittests will pass.<= div><div></div><div class=3D"h5"><br><br><div class=3D"gmail_quote">On Wed,= Jul 28, 2010 at 11:15 PM, Andrej Mitrovic <span dir=3D"ltr">&lt;<a href=3D= "mailto:andrej.mitrovich gmail.com" target=3D"_blank">andrej.mitrovich gmai= l.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Should I just kee= p posting my findings in this thread? I hate to make a new thread for every= problem I find.. <br> <br>Anyway, on Page 150, this code fails:<br><br>auto f =3D (int i) {};<br>= assert(is(f =3D=3D function));<br><br>I&#39;ve checked via typeid(), and f = is a delegate by default, not a function. I&#39;ve tested it both in a func= tion&#39;s scope and in module scope, with the same results.<div> <div></div><div><br> <br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 10:56 PM, Rainer Sch= uetze <span dir=3D"ltr">&lt;<a href=3D"mailto:r.sagitario gmx.de" target=3D= "_blank">r.sagitario gmx.de</a>&gt;</span> wrote:<br><blockquote class=3D"g= mail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(= 204, 204, 204); padding-left: 1ex;"> <br> Andrej Mitrovic wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> Woops, I got confused. I was thinking about structs, not arrays.<div><br> <br> But yeah, in this case a float gets compared to a double and it seems to ev= aluate to false.<br> </div></blockquote> <br> 2.4 has no exact representation as a floating point value, as it is 2^^2*0.= 6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after= 53 bits for a double. As a result<br> <br> =A0 =A0 =A0 =A0float f =3D 2.4; // approximately 2.4000001<br> =A0 =A0 =A0 =A0double d =3D 2.4; // approximately 2.3999999999999999<br> =A0 =A0 =A0 =A0assert(f =3D=3D d);<br> <br> fails, because the comparison is done after converting the truncated float = to double (as long as the compiler does not issue SSE instructions with sin= gle precision).<br> <br> In contrast, this<br> <br> =A0 =A0 =A0 =A0assert(2.4 =3D=3D 2.4f);<br> <br> passes, as the compiler keeps real precision until writing the value to mem= ory and evaluates the expression at compile time.<br> </blockquote></div><br> </div></div></blockquote></div><br> </div></div></blockquote></div><br> --002215b01d52d98d36048c881ab1--
Jul 29 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016e6d7e352cc805d048c8d6851
Content-Type: text/plain; charset=ISO-8859-1

How do I print out an expanded tuple but with spaces between the values?
There's this example on page 164:

import std.typecons, std.stdio;

void fun(T...)(T args) {
    // create a tuple to pack all arguments together
    gun(tuple(args));
}

void gun(T)(T value) {
    // expand the tuple back
    writeln(value.expand);
}

void main() {
    fun(1);
    fun(1, 2.2);
}

This prints out:
1
12.2

But that's confusing, since the values are "glued" together when printed
out. I really want to print out:
1
1 2.2

Any ideas?

One other thing. I can use the .length property for value and parameter
tuples, but only if I haven't built them myself with the call to
std.typecons.tuple(). For example I can call writeln(T.length) in the fun()
function (where the compiler automatically constructs a tuple), but not in
the gun() function. So there seems to be compiler tuples and
user-constructed tuples, which are not the same.

It's a bit of a shame that there isn't a chapter on tuples except this brief
mention (I don't see it listed in the contents page). I guess I'll take a
look at the implementation.

On Thu, Jul 29, 2010 at 5:08 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 Page 160, code:

 import std.algorithm, std.range;

 void main() {}

 double average() { return 1.0; }
 double average(double) { return 2.0; }

 // computes average of a set of numbers, passable directly or via an array
 double average(double[] values...) {
     if (values.empty) {
         throw new Exception("Average of zero elements in undefined");
     }
     return reduce!((a, b) { return a + b; })(0.0, values) / values.length;
 }

 unittest {
     average();
     average(2.5);
 }


 The book states this is an ambiguous call, but I can succesfully compile.


 On Thu, Jul 29, 2010 at 4:16 AM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 I can't get the example on page 158 to compile, I've tried both versions
 of reduce:

 import std.stdio, std.range;

  property bool empty(T)(T[] a) { return a.length == 0; }
  property ref T front(T)(T[] a) { return a[0]; }
 void popFront(T)(ref T[] a) { a = a[1 .. $]; }

 V reduce(alias fun, V, R)(V x, R range)
     if (isInputRange!R && is(typeof(x = fun(x, range.front))))
 {
     for (; !range.empty; range.popFront()) {
         x = fun(x, range.front);
     }
     return x;
 }

 unittest {
     int[] r = [10, 14, 3, 5, 23];

     // compute the sum of all elements
     int sum = reduce!((a, b) { return a + b; })(0, r);
     assert(sum == 55);

     // compute minimum
     int min = reduce!((a, b) { return a < b ? a : b; })(r[0], r);
     assert(min == 3);
 }

 void main() { }

 Errors:
 reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
 (isInputRange!(R) && is(typeof(x = fun(x,range.front)))) does not match any
 function template declaration

 reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if
 (isInputRange!(R) && is(typeof(x = fun(x,range.front)))) cannot deduce
 template function from argument types !(__dgliteral1)(int,int[])

 reduce.d(31): Error: template instance errors instantiating template

 If I comment out the template constraints (the if statements for either
 version of reduce), the example will compile and the unittests will pass.


 On Wed, Jul 28, 2010 at 11:15 PM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 Should I just keep posting my findings in this thread? I hate to make a
 new thread for every problem I find..

 Anyway, on Page 150, this code fails:

 auto f = (int i) {};
 assert(is(f == function));

 I've checked via typeid(), and f is a delegate by default, not a
 function. I've tested it both in a function's scope and in module scope,
 with the same results.


 On Wed, Jul 28, 2010 at 10:56 PM, Rainer Schuetze <r.sagitario gmx.de>wrote:

 Andrej Mitrovic wrote:

 Woops, I got confused. I was thinking about structs, not arrays.


 But yeah, in this case a float gets compared to a double and it seems
 to evaluate to false.

2.4 has no exact representation as a floating point value, as it is 2^^2*0.6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after 53 bits for a double. As a result float f = 2.4; // approximately 2.4000001 double d = 2.4; // approximately 2.3999999999999999 assert(f == d); fails, because the comparison is done after converting the truncated float to double (as long as the compiler does not issue SSE instructions with single precision). In contrast, this assert(2.4 == 2.4f); passes, as the compiler keeps real precision until writing the value to memory and evaluates the expression at compile time.




--0016e6d7e352cc805d048c8d6851 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable How do I print out an expanded tuple but with spaces between the values? Th= ere&#39;s this example on page 164:<br><br>import std.typecons, std.stdio;<= br><br>void fun(T...)(T args) {<br>=A0=A0=A0 // create a tuple to pack all = arguments together<br> =A0=A0=A0 gun(tuple(args));<br>}<br><br>void gun(T)(T value) {=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 <br>=A0=A0=A0 // exp= and the tuple back<br>=A0=A0=A0 writeln(value.expand);<br>}<br><br>void mai= n() {<br>=A0=A0=A0 fun(1);<br>=A0=A0=A0 fun(1, 2.2);<br>}<br><br>This print= s out:<br> 1<br>12.2<br><br>But that&#39;s confusing, since the values are &quot;glued= &quot; together when printed out. I really want to print out:<br>1<br>1 2.2= <br><br>Any ideas?<br><br>One other thing. I can use the .length property f= or value and parameter tuples, but only if I haven&#39;t built them myself = with the call to std.typecons.tuple(). For example I can call writeln(T.len= gth) in the fun() function (where the compiler automatically constructs a t= uple), but not in the gun() function. So there seems to be compiler tuples = and user-constructed tuples, which are not the same. <br> <br>It&#39;s a bit of a shame that there isn&#39;t a chapter on tuples exce= pt this brief mention (I don&#39;t see it listed in the contents page). I g= uess I&#39;ll take a look at the implementation.<br><br><div class=3D"gmail= _quote"> On Thu, Jul 29, 2010 at 5:08 PM, Andrej Mitrovic <span dir=3D"ltr">&lt;<a h= ref=3D"mailto:andrej.mitrovich gmail.com">andrej.mitrovich gmail.com</a>&gt= ;</span> wrote:<br><blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0= pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;= "> Page 160, code:<br><br>import std.algorithm, std.range;<br><br>void main() = {}<br><br>double average() { return 1.0; }<br>double average(double) { retu= rn 2.0; }<br><br>// computes average of a set of numbers, passable directly= or via an array<br> double average(double[] values...) {<br>=A0=A0=A0 if (values.empty) {<br>= =A0=A0=A0=A0=A0=A0=A0 throw new Exception(&quot;Average of zero elements in= undefined&quot;);<br>=A0=A0=A0 }<br>=A0=A0=A0 return reduce!((a, b) { retu= rn a + b; })(0.0, values) / values.length;<br> }<br><br>unittest {<br>=A0=A0=A0 average();<br>=A0=A0=A0 average(2.5);<br>}= <br><br><br>The book states this is an ambiguous call, but I can succesfull= y compile.<div><div></div><div class=3D"h5"><br><br><div class=3D"gmail_quo= te">On Thu, Jul 29, 2010 at 4:16 AM, Andrej Mitrovic <span dir=3D"ltr">&lt;= <a href=3D"mailto:andrej.mitrovich gmail.com" target=3D"_blank">andrej.mitr= ovich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">I can&#39;t get t= he example on page 158 to compile, I&#39;ve tried both versions of reduce:<= br> <br>import std.stdio, std.range;<br><br> property bool empty(T)(T[] a) { re= turn a.length =3D=3D 0; }<br> property ref T front(T)(T[] a) { return a[0];= }<br> void popFront(T)(ref T[] a) { a =3D a[1 .. $]; }<br><br>V reduce(alias fun,= V, R)(V x, R range)<br>=A0=A0=A0 if (isInputRange!R &amp;&amp; is(typeof(x= =3D fun(x, range.front))))<br>{<br>=A0=A0=A0 for (; !range.empty; range.po= pFront()) {<br> =A0=A0=A0=A0=A0=A0=A0 x =3D fun(x, range.front);<br>=A0=A0=A0 }<br>=A0=A0= =A0 return x;<br>}<br><br>unittest {<br>=A0=A0=A0 int[] r =3D [10, 14, 3, 5= , 23];<br>=A0=A0=A0 <br>=A0=A0=A0 // compute the sum of all elements<br>=A0= =A0=A0 int sum =3D reduce!((a, b) { return a + b; })(0, r);<br> =A0=A0=A0 assert(sum =3D=3D 55);<br>=A0=A0=A0 <br>=A0=A0=A0 // compute mini= mum<br>=A0=A0=A0 int min =3D reduce!((a, b) { return a &lt; b ? a : b; })(r= [0], r);<br>=A0=A0=A0 assert(min =3D=3D 3);<br>}<br><br>void main() { }<br>= <br>Errors:<br>reduce.d(31): Error: template reduce.reduce(alias fun,V,R) i= f (isInputRange!(R) &amp;&amp; is(typeof(x =3D fun(x,range.front)))) does n= ot match any function template declaration<br> <br>reduce.d(31): Error: template reduce.reduce(alias fun,V,R) if (isInputR= ange!(R) &amp;&amp; is(typeof(x =3D fun(x,range.front)))) cannot deduce tem= plate function from argument types !(__dgliteral1)(int,int[])<br><br>reduce= .d(31): Error: template instance errors instantiating template<br> <br>If I comment out the template constraints (the if statements for either= version of reduce), the example will compile and the unittests will pass.<= div><div></div><div><br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010= at 11:15 PM, Andrej Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andre= j.mitrovich gmail.com" target=3D"_blank">andrej.mitrovich gmail.com</a>&gt;= </span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Should I just kee= p posting my findings in this thread? I hate to make a new thread for every= problem I find.. <br> <br>Anyway, on Page 150, this code fails:<br><br>auto f =3D (int i) {};<br>= assert(is(f =3D=3D function));<br><br>I&#39;ve checked via typeid(), and f = is a delegate by default, not a function. I&#39;ve tested it both in a func= tion&#39;s scope and in module scope, with the same results.<div> <div></div><div><br> <br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 10:56 PM, Rainer Sch= uetze <span dir=3D"ltr">&lt;<a href=3D"mailto:r.sagitario gmx.de" target=3D= "_blank">r.sagitario gmx.de</a>&gt;</span> wrote:<br><blockquote class=3D"g= mail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(= 204, 204, 204); padding-left: 1ex;"> <br> Andrej Mitrovic wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> Woops, I got confused. I was thinking about structs, not arrays.<div><br> <br> But yeah, in this case a float gets compared to a double and it seems to ev= aluate to false.<br> </div></blockquote> <br> 2.4 has no exact representation as a floating point value, as it is 2^^2*0.= 6, so the mantissa is 3/5. It is rounded after 24 bits for float, but after= 53 bits for a double. As a result<br> <br> =A0 =A0 =A0 =A0float f =3D 2.4; // approximately 2.4000001<br> =A0 =A0 =A0 =A0double d =3D 2.4; // approximately 2.3999999999999999<br> =A0 =A0 =A0 =A0assert(f =3D=3D d);<br> <br> fails, because the comparison is done after converting the truncated float = to double (as long as the compiler does not issue SSE instructions with sin= gle precision).<br> <br> In contrast, this<br> <br> =A0 =A0 =A0 =A0assert(2.4 =3D=3D 2.4f);<br> <br> passes, as the compiler keeps real precision until writing the value to mem= ory and evaluates the expression at compile time.<br> </blockquote></div><br> </div></div></blockquote></div><br> </div></div></blockquote></div><br> </div></div></blockquote></div><br> --0016e6d7e352cc805d048c8d6851--
Jul 29 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--0016e6d58a03fdb3cd048c981234
Content-Type: text/plain; charset=ISO-8859-1

On Thu, Jul 29, 2010 at 23:28, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

 How do I print out an expanded tuple but with spaces between the values?
 There's this example on page 164:

 import std.typecons, std.stdio;

 void fun(T...)(T args) {
     // create a tuple to pack all arguments together
     gun(tuple(args));
 }

 void gun(T)(T value) {
     // expand the tuple back
     writeln(value.expand);
 }

 void main() {
     fun(1);
     fun(1, 2.2);
 }

 This prints out:
 1
 12.2

 But that's confusing, since the values are "glued" together when printed
 out. I really want to print out:
 1
 1 2.2

 Any ideas?

You can iterate on the values and create the corresponding string. Note that you must have a polymorphic function to map on a tuple's elements. void gun(T)(T value) { string result; foreach(index, Type; value.expand) { result ~= to!string(value.expand[i]) ~ " "; } writeln(result); } There will be a surnumerary " " at the very end, but I prefer to show the way to iterate on a tuple. value is a std.typecons.Tuple, but value.expand gives access to the raw (T...) tuple inside it.
 One other thing. I can use the .length property for value and parameter
 tuples, but only if I haven't built them myself with the call to
 std.typecons.tuple(). For example I can call writeln(T.length) in the fun()
 function (where the compiler automatically constructs a tuple), but not in
 the gun() function. So there seems to be compiler tuples and
 user-constructed tuples, which are not the same.

Yes, std.typecons.Tuple should have a length, it's trivial to add. It's issue #4381 http://d.puremagic.com/issues/show_bug.cgi?id=4381 And yes, there are 'raw', compiler-managed tuples which are lists of types and values 'glued' together. They are powerful, iterable, indexable, slicable, know their length, etc. They may even be assignable. Ah, in fact, they can hold anything that can be passed as a template argument, I guess. But, being a bunch of many different types, they cannot be returned by a function. That's C inheritance for you. They have no .init value neither, which I found too bad for generic code. http://d.puremagic.com/issues/show_bug.cgi?id=4536 So std.typecons.Tuple provides a way to wrap values inside a struct, while giving access to the types and values, and that can be returned by a function. It can also have named members, which can be quite handy when you return many things from a function, grouped inside a tuple. Tuple!("index", int, "sum", double) t = tuple(1,3.14); assert(t.index== 1); // t has .first and .second as members. assert(t.sum== 3.14);
 It's a bit of a shame that there isn't a chapter on tuples except this
 brief mention (I don't see it listed in the contents page). I guess I'll
 take a look at the implementation.

in flux while he was writing this. D the language will not change much for some time, while the standard library is being actively transformed, if only to take into account the new features that were added for the past 6 months. btw, I like you posts, but do not always have the time to answer them. If among the numerous issues you posted there there is still one that bother you, do not hesitate to ask again for an answer. Philippe --0016e6d58a03fdb3cd048c981234 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Thu, Jul 29, 2010 at 23:28, Andrej Mitrovic <= span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andrej.m= itrovich gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quot= e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"=

ere&#39;s this example on page 164:<br><br>import std.typecons, std.stdio;<= br><br>void fun(T...)(T args) {<br>=A0=A0=A0 // create a tuple to pack all = arguments together<br> =A0=A0=A0 gun(tuple(args));<br>}<br><br>void gun(T)(T value) {=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 <br>=A0=A0=A0 // exp= and the tuple back<br>=A0=A0=A0 writeln(value.expand);<br>}<br><br>void mai= n() {<br>=A0=A0=A0 fun(1);<br>=A0=A0=A0 fun(1, 2.2);<br>}<br><br>This print= s out:<br> 1<br>12.2<br><br>But that&#39;s confusing, since the values are &quot;glued= &quot; together when printed out. I really want to print out:<br>1<br>1 2.2= <br><br>Any ideas?<br></blockquote><div><br></div><div>You can iterate on t= he values and create the corresponding string. Note that you must have a po= lymorphic function to map on a tuple&#39;s elements.</div> <div><br></div><div>void gun(T)(T value)</div><div>{</div><div>=A0=A0 =A0st= ring result;</div><div>=A0=A0 =A0foreach(index, Type; value.expand)</div><d= iv>=A0=A0 =A0{</div><div>=A0=A0 =A0 =A0 =A0result ~=3D to!string(value.expa= nd[i]) ~ &quot; =A0&quot;;</div> <div>=A0=A0 =A0}</div><div>=A0=A0 =A0writeln(result);</div><div>}</div><div=
<br></div><div>There will be a surnumerary &quot; &quot; at the very end, =

.Tuple, but value.expand gives access to the raw (T...) tuple inside it.</d= iv> <div><br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"mar= gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>One other = thing. I can use the .length property for value and parameter tuples, but o= nly if I haven&#39;t built them myself with the call to std.typecons.tuple(= ). For example I can call writeln(T.length) in the fun() function (where th= e compiler automatically constructs a tuple), but not in the gun() function= . So there seems to be compiler tuples and user-constructed tuples, which a= re not the same. <br> </blockquote><div><br></div><div>Yes, std.typecons.Tuple should have a leng= th, it&#39;s trivial to add. It&#39;s issue #4381</div><div><br></div><div>= <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4381">http://d.p= uremagic.com/issues/show_bug.cgi?id=3D4381</a></div> <div><br></div><div>And yes, there are &#39;raw&#39;, compiler-managed tupl= es which are lists of types and values &#39;glued&#39; together. They are p= owerful, iterable, indexable, slicable, know their length, etc. They may ev= en be assignable. Ah, in fact, they can hold anything that can be passed as= a template argument, I guess.</div> <div>But, being a bunch of many different types, they cannot be returned by= a function. That&#39;s C inheritance for you. They have no .init value nei= ther, which I found too bad for generic code.</div><div><br></div><div> <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4536">http://d.p= uremagic.com/issues/show_bug.cgi?id=3D4536</a></div><div><br></div><div>So = std.typecons.Tuple provides a way to wrap values inside a struct, while giv= ing access to the types and values, and that can be returned by a function.= It can also have named members, which can be quite handy when you return m= any things from a function, grouped inside a tuple.</div> <div><br></div><div>Tuple!(&quot;index&quot;, int, &quot;sum&quot;, double)= t =3D tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // = t has .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</d= iv><div> <br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0= 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <br>It&#39;s a bit of a shame that there isn&#39;t a chapter on tuples exce= pt this brief mention (I don&#39;t see it listed in the contents page). I g= uess I&#39;ll take a look at the implementation.<div><div></div><div class= =3D"h5"> <br></div></div></blockquote><div><br></div><div>Andrei didn&#39;t want to = talk too much about Phobos, as it was (ans still is!) in flux while he was = writing this. D the language will not change much for some time, while the = standard library is being actively transformed, if only to take into accoun= t the new features that were added for the past 6 months.</div> <div><br></div><div>btw, I like you posts, but do not always have the time = to answer them. If among the numerous issues you posted there there is stil= l one that bother you, do not hesitate to ask again for an answer.</div> <div><br></div><div>=A0Philippe</div></div> --0016e6d58a03fdb3cd048c981234--
Jul 30 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--002215976302ffba1a048c9a1473
Content-Type: text/plain; charset=ISO-8859-1

Thanks Phillippe, that explains a lot.

I like to try out all the examples, I never take any of it for granted. But
hardly any book comes with 100% working examples, even the much praised CPL
is loaded with syntax mistakes. With that said I have to admit I'm really
enjoying reading TDPL so far.

On Fri, Jul 30, 2010 at 12:11 PM, Philippe Sigaud <philippe.sigaud gmail.com
 wrote:

 On Thu, Jul 29, 2010 at 23:28, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 How do I print out an expanded tuple but with spaces between the values?
 There's this example on page 164:

 import std.typecons, std.stdio;

 void fun(T...)(T args) {
     // create a tuple to pack all arguments together
     gun(tuple(args));
 }

 void gun(T)(T value) {
     // expand the tuple back
     writeln(value.expand);
 }

 void main() {
     fun(1);
     fun(1, 2.2);
 }

 This prints out:
 1
 12.2

 But that's confusing, since the values are "glued" together when printed
 out. I really want to print out:
 1
 1 2.2

 Any ideas?

You can iterate on the values and create the corresponding string. Note that you must have a polymorphic function to map on a tuple's elements. void gun(T)(T value) { string result; foreach(index, Type; value.expand) { result ~= to!string(value.expand[i]) ~ " "; } writeln(result); } There will be a surnumerary " " at the very end, but I prefer to show the way to iterate on a tuple. value is a std.typecons.Tuple, but value.expand gives access to the raw (T...) tuple inside it.
 One other thing. I can use the .length property for value and parameter
 tuples, but only if I haven't built them myself with the call to
 std.typecons.tuple(). For example I can call writeln(T.length) in the fun()
 function (where the compiler automatically constructs a tuple), but not in
 the gun() function. So there seems to be compiler tuples and
 user-constructed tuples, which are not the same.

Yes, std.typecons.Tuple should have a length, it's trivial to add. It's issue #4381 http://d.puremagic.com/issues/show_bug.cgi?id=4381 And yes, there are 'raw', compiler-managed tuples which are lists of types and values 'glued' together. They are powerful, iterable, indexable, slicable, know their length, etc. They may even be assignable. Ah, in fact, they can hold anything that can be passed as a template argument, I guess. But, being a bunch of many different types, they cannot be returned by a function. That's C inheritance for you. They have no .init value neither, which I found too bad for generic code. http://d.puremagic.com/issues/show_bug.cgi?id=4536 So std.typecons.Tuple provides a way to wrap values inside a struct, while giving access to the types and values, and that can be returned by a function. It can also have named members, which can be quite handy when you return many things from a function, grouped inside a tuple. Tuple!("index", int, "sum", double) t = tuple(1,3.14); assert(t.index== 1); // t has .first and .second as members. assert(t.sum== 3.14);
 It's a bit of a shame that there isn't a chapter on tuples except this
 brief mention (I don't see it listed in the contents page). I guess I'll
 take a look at the implementation.

in flux while he was writing this. D the language will not change much for some time, while the standard library is being actively transformed, if only to take into account the new features that were added for the past 6 months. btw, I like you posts, but do not always have the time to answer them. If among the numerous issues you posted there there is still one that bother you, do not hesitate to ask again for an answer. Philippe

--002215976302ffba1a048c9a1473 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Thanks Phillippe, that explains a lot.<br><br>I like to try out all the exa= mples, I never take any of it for granted. But hardly any book comes with 1= 00% working examples, even the much praised CPL is loaded with syntax mista= kes. With that said I have to admit I&#39;m really enjoying reading TDPL so= far.<br> <br><div class=3D"gmail_quote"> On Fri, Jul 30, 2010 at 12:11 PM, Philippe Sigaud <span dir=3D"ltr">&lt;<a = href=3D"mailto:philippe.sigaud gmail.com" target=3D"_blank">philippe.sigaud= 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); p= adding-left: 1ex;"> <div class=3D"gmail_quote"><div>On Thu, Jul 29, 2010 at 23:28, Andrej Mitro= vic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com" tar= get=3D"_blank">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockqu= ote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: = 1px solid rgb(204, 204, 204); padding-left: 1ex;"> How do I print out an expanded tuple but with spaces between the values? Th= ere&#39;s this example on page 164:<br><br>import std.typecons, std.stdio;<= br><br>void fun(T...)(T args) {<br>=A0=A0=A0 // create a tuple to pack all = arguments together<br> =A0=A0=A0 gun(tuple(args));<br>}<br><br>void gun(T)(T value) {=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 <br>=A0=A0=A0 // exp= and the tuple back<br>=A0=A0=A0 writeln(value.expand);<br>}<br><br>void mai= n() {<br>=A0=A0=A0 fun(1);<br>=A0=A0=A0 fun(1, 2.2);<br>}<br><br>This print= s out:<br> 1<br>12.2<br><br>But that&#39;s confusing, since the values are &quot;glued= &quot; together when printed out. I really want to print out:<br>1<br>1 2.2= <br><br>Any ideas?<br></blockquote><div><br></div></div><div>You can iterat= e on the values and create the corresponding string. Note that you must hav= e a polymorphic function to map on a tuple&#39;s elements.</div> <div> <div><br></div><div>void gun(T)(T value)</div><div>{</div></div><div>=A0=A0= =A0string result;</div><div>=A0=A0 =A0foreach(index, Type; value.expand)</= div><div>=A0=A0 =A0{</div><div>=A0=A0 =A0 =A0 =A0result ~=3D to!string(valu= e.expand[i]) ~ &quot; =A0&quot;;</div> <div>=A0=A0 =A0}</div><div>=A0=A0 =A0writeln(result);</div><div>}</div><div=
<br></div><div>There will be a surnumerary &quot; &quot; at the very end, =

.Tuple, but value.expand gives access to the raw (T...) tuple inside it.</d= iv> <div> <div><br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"mar= gin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-= left: 1ex;"><br>One other thing. I can use the .length property for value a= nd parameter tuples, but only if I haven&#39;t built them myself with the c= all to std.typecons.tuple(). For example I can call writeln(T.length) in th= e fun() function (where the compiler automatically constructs a tuple), but= not in the gun() function. So there seems to be compiler tuples and user-c= onstructed tuples, which are not the same. <br> </blockquote><div><br></div></div><div>Yes, std.typecons.Tuple should have = a length, it&#39;s trivial to add. It&#39;s issue #4381</div><div><br></div=
<div><a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4381" targ=


<div><br></div><div>And yes, there are &#39;raw&#39;, compiler-managed tupl= es which are lists of types and values &#39;glued&#39; together. They are p= owerful, iterable, indexable, slicable, know their length, etc. They may ev= en be assignable. Ah, in fact, they can hold anything that can be passed as= a template argument, I guess.</div> <div>But, being a bunch of many different types, they cannot be returned by= a function. That&#39;s C inheritance for you. They have no .init value nei= ther, which I found too bad for generic code.</div><div><br></div><div> <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4536" target=3D"= _blank">http://d.puremagic.com/issues/show_bug.cgi?id=3D4536</a></div><div>= <br></div><div>So std.typecons.Tuple provides a way to wrap values inside a= struct, while giving access to the types and values, and that can be retur= ned by a function. It can also have named members, which can be quite handy= when you return many things from a function, grouped inside a tuple.</div> <div><br></div><div>Tuple!(&quot;index&quot;, int, &quot;sum&quot;, double)= t =3D tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // = t has .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</d= iv><div> <div> <br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: = 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left:= 1ex;"> <br>It&#39;s a bit of a shame that there isn&#39;t a chapter on tuples exce= pt this brief mention (I don&#39;t see it listed in the contents page). I g= uess I&#39;ll take a look at the implementation.<div><div></div><div> <br></div></div></blockquote><div><br></div></div><div>Andrei didn&#39;t wa= nt to talk too much about Phobos, as it was (ans still is!) in flux while h= e was writing this. D the language will not change much for some time, whil= e the standard library is being actively transformed, if only to take into = account the new features that were added for the past 6 months.</div> <div><br></div><div>btw, I like you posts, but do not always have the time = to answer them. If among the numerous issues you posted there there is stil= l one that bother you, do not hesitate to ask again for an answer.</div> <div><br></div><font color=3D"#888888"><div>=A0Philippe</div></font></div> </blockquote></div><br> --002215976302ffba1a048c9a1473--
Jul 30 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016364c7a4d0e02bf048c9ee990
Content-Type: text/plain; charset=ISO-8859-1

Hey, just tried out your code.

In the first one there's a little typo (used 'i' instead of index), but
that's ok. ;p

It seems like I don't need to use the to!() template. This code seems to
work fine:

void gun(T)(T value) {
    foreach(Type; value.expand)
        write(Type, " ");

    writeln();
}

But regardless, at least I now know how to traverse through my own tuples,
so thanks for that one.

In your second example:

Tuple!("index", int, "sum", double) t = tuple(1,3.14);

assert(t.index== 1); // t has .first and .second as members.
assert(t.sum== 3.14);

I get an error way deep in the library itself (this could call for a better
error message, methinks):
C:\DMD\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(320): Error: tuple
index 2 exceeds 2

I've reversed the order, put types before identifiers and this works fine
then:

Tuple!(int, "index", double, "sum") t = tuple(1, 3.14);

I'm not sure what you mean by "t has .first and .second as members", I can't
seem to access those. Maybe you meant t.index and t.sum as members?


On Fri, Jul 30, 2010 at 12:11 PM, Philippe Sigaud <philippe.sigaud gmail.com
 wrote:

 On Thu, Jul 29, 2010 at 23:28, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 How do I print out an expanded tuple but with spaces between the values?
 There's this example on page 164:

 import std.typecons, std.stdio;

 void fun(T...)(T args) {
     // create a tuple to pack all arguments together
     gun(tuple(args));
 }

 void gun(T)(T value) {
     // expand the tuple back
     writeln(value.expand);
 }

 void main() {
     fun(1);
     fun(1, 2.2);
 }

 This prints out:
 1
 12.2

 But that's confusing, since the values are "glued" together when printed
 out. I really want to print out:
 1
 1 2.2

 Any ideas?

You can iterate on the values and create the corresponding string. Note that you must have a polymorphic function to map on a tuple's elements. void gun(T)(T value) { string result; foreach(index, Type; value.expand) { result ~= to!string(value.expand[i]) ~ " "; } writeln(result); } There will be a surnumerary " " at the very end, but I prefer to show the way to iterate on a tuple. value is a std.typecons.Tuple, but value.expand gives access to the raw (T...) tuple inside it.
 One other thing. I can use the .length property for value and parameter
 tuples, but only if I haven't built them myself with the call to
 std.typecons.tuple(). For example I can call writeln(T.length) in the fun()
 function (where the compiler automatically constructs a tuple), but not in
 the gun() function. So there seems to be compiler tuples and
 user-constructed tuples, which are not the same.

Yes, std.typecons.Tuple should have a length, it's trivial to add. It's issue #4381 http://d.puremagic.com/issues/show_bug.cgi?id=4381 And yes, there are 'raw', compiler-managed tuples which are lists of types and values 'glued' together. They are powerful, iterable, indexable, slicable, know their length, etc. They may even be assignable. Ah, in fact, they can hold anything that can be passed as a template argument, I guess. But, being a bunch of many different types, they cannot be returned by a function. That's C inheritance for you. They have no .init value neither, which I found too bad for generic code. http://d.puremagic.com/issues/show_bug.cgi?id=4536 So std.typecons.Tuple provides a way to wrap values inside a struct, while giving access to the types and values, and that can be returned by a function. It can also have named members, which can be quite handy when you return many things from a function, grouped inside a tuple. Tuple!("index", int, "sum", double) t = tuple(1,3.14); assert(t.index== 1); // t has .first and .second as members. assert(t.sum== 3.14);
 It's a bit of a shame that there isn't a chapter on tuples except this
 brief mention (I don't see it listed in the contents page). I guess I'll
 take a look at the implementation.

in flux while he was writing this. D the language will not change much for some time, while the standard library is being actively transformed, if only to take into account the new features that were added for the past 6 months. btw, I like you posts, but do not always have the time to answer them. If among the numerous issues you posted there there is still one that bother you, do not hesitate to ask again for an answer. Philippe

--0016364c7a4d0e02bf048c9ee990 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Hey, just tried out your code.<br><br>In the first one there&#39;s a little= typo (used &#39;i&#39; instead of index), but that&#39;s ok. ;p<br><br>It = seems like I don&#39;t need to use the to!() template. This code seems to w= ork fine:<br> <br>void gun(T)(T value) {<br>=A0=A0=A0 foreach(Type; value.expand)<br>=A0= =A0=A0=A0=A0=A0=A0 write(Type, &quot; &quot;);<br>=A0=A0=A0 <br>=A0=A0=A0 w= riteln();<br>}<br><br>But regardless, at least I now know how to traverse t= hrough my own tuples, so thanks for that one.<br> <br>In your second example:<br><div><br></div><div>Tuple!(&quot;index&quot;= , int, &quot;sum&quot;, double) t =3D=20 tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // t has= =20 .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</div> <br>I get an error way deep in the library itself (this could call for a be= tter error message, methinks):<br>C:\DMD\dmd2\windows\bin\..\..\src\phobos\= std\typecons.d(320): Error: tuple index 2 exceeds 2<br><br>I&#39;ve reverse= d the order, put types before identifiers and this works fine then:<br> <br>Tuple!(int, &quot;index&quot;, double, &quot;sum&quot;) t =3D tuple(1, = 3.14);<br><br>I&#39;m not sure what you mean by &quot;t has .first and .sec= ond as members&quot;, I can&#39;t seem to access those. Maybe you meant t.i= ndex and t.sum as members?<br> <br><br><div class=3D"gmail_quote">On Fri, Jul 30, 2010 at 12:11 PM, Philip= pe Sigaud <span dir=3D"ltr">&lt;<a href=3D"mailto:philippe.sigaud gmail.com= ">philippe.sigaud gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"g= mail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(= 204, 204, 204); padding-left: 1ex;"> <div class=3D"gmail_quote"><div class=3D"im">On Thu, Jul 29, 2010 at 23:28,= Andrej Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich g= mail.com" target=3D"_blank">andrej.mitrovich 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;"> How do I print out an expanded tuple but with spaces between the values? Th= ere&#39;s this example on page 164:<br><br>import std.typecons, std.stdio;<= br><br>void fun(T...)(T args) {<br>=A0=A0=A0 // create a tuple to pack all = arguments together<br> =A0=A0=A0 gun(tuple(args));<br>}<br><br>void gun(T)(T value) {=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 <br>=A0=A0=A0 // exp= and the tuple back<br>=A0=A0=A0 writeln(value.expand);<br>}<br><br>void mai= n() {<br>=A0=A0=A0 fun(1);<br>=A0=A0=A0 fun(1, 2.2);<br>}<br><br>This print= s out:<br> 1<br>12.2<br><br>But that&#39;s confusing, since the values are &quot;glued= &quot; together when printed out. I really want to print out:<br>1<br>1 2.2= <br><br>Any ideas?<br></blockquote><div><br></div></div><div>You can iterat= e on the values and create the corresponding string. Note that you must hav= e a polymorphic function to map on a tuple&#39;s elements.</div> <div class=3D"im"> <div><br></div><div>void gun(T)(T value)</div><div>{</div></div><div>=A0=A0= =A0string result;</div><div>=A0=A0 =A0foreach(index, Type; value.expand)</= div><div>=A0=A0 =A0{</div><div>=A0=A0 =A0 =A0 =A0result ~=3D to!string(valu= e.expand[i]) ~ &quot; =A0&quot;;</div> <div>=A0=A0 =A0}</div><div>=A0=A0 =A0writeln(result);</div><div>}</div><div=
<br></div><div>There will be a surnumerary &quot; &quot; at the very end, =

.Tuple, but value.expand gives access to the raw (T...) tuple inside it.</d= iv> <div class=3D"im"> <div><br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"mar= gin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-= left: 1ex;"><br>One other thing. I can use the .length property for value a= nd parameter tuples, but only if I haven&#39;t built them myself with the c= all to std.typecons.tuple(). For example I can call writeln(T.length) in th= e fun() function (where the compiler automatically constructs a tuple), but= not in the gun() function. So there seems to be compiler tuples and user-c= onstructed tuples, which are not the same. <br> </blockquote><div><br></div></div><div>Yes, std.typecons.Tuple should have = a length, it&#39;s trivial to add. It&#39;s issue #4381</div><div><br></div=
<div><a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4381" targ=


<div><br></div><div>And yes, there are &#39;raw&#39;, compiler-managed tupl= es which are lists of types and values &#39;glued&#39; together. They are p= owerful, iterable, indexable, slicable, know their length, etc. They may ev= en be assignable. Ah, in fact, they can hold anything that can be passed as= a template argument, I guess.</div> <div>But, being a bunch of many different types, they cannot be returned by= a function. That&#39;s C inheritance for you. They have no .init value nei= ther, which I found too bad for generic code.</div><div><br></div><div> <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4536" target=3D"= _blank">http://d.puremagic.com/issues/show_bug.cgi?id=3D4536</a></div><div>= <br></div><div>So std.typecons.Tuple provides a way to wrap values inside a= struct, while giving access to the types and values, and that can be retur= ned by a function. It can also have named members, which can be quite handy= when you return many things from a function, grouped inside a tuple.</div> <div><br></div><div>Tuple!(&quot;index&quot;, int, &quot;sum&quot;, double)= t =3D tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // = t has .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</d= iv><div class=3D"im"> <div> <br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: = 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left:= 1ex;"> <br>It&#39;s a bit of a shame that there isn&#39;t a chapter on tuples exce= pt this brief mention (I don&#39;t see it listed in the contents page). I g= uess I&#39;ll take a look at the implementation.<div><div></div><div> <br></div></div></blockquote><div><br></div></div><div>Andrei didn&#39;t wa= nt to talk too much about Phobos, as it was (ans still is!) in flux while h= e was writing this. D the language will not change much for some time, whil= e the standard library is being actively transformed, if only to take into = account the new features that were added for the past 6 months.</div> <div><br></div><div>btw, I like you posts, but do not always have the time = to answer them. If among the numerous issues you posted there there is stil= l one that bother you, do not hesitate to ask again for an answer.</div> <div><br></div><font color=3D"#888888"><div>=A0Philippe</div></font></div> </blockquote></div><br> --0016364c7a4d0e02bf048c9ee990--
Jul 30 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016e6d9a3302ae602048c9f5d0e
Content-Type: text/plain; charset=ISO-8859-1

I've found that the syntax mytuple.field[] can be used, I think this is
probably what you meant by .first and .second.


On Fri, Jul 30, 2010 at 8:20 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 Hey, just tried out your code.

 In the first one there's a little typo (used 'i' instead of index), but
 that's ok. ;p

 It seems like I don't need to use the to!() template. This code seems to
 work fine:


 void gun(T)(T value) {
     foreach(Type; value.expand)
         write(Type, " ");

     writeln();
 }

 But regardless, at least I now know how to traverse through my own tuples,
 so thanks for that one.

 In your second example:


 Tuple!("index", int, "sum", double) t = tuple(1,3.14);

 assert(t.index== 1); // t has .first and .second as members.
 assert(t.sum== 3.14);

 I get an error way deep in the library itself (this could call for a better
 error message, methinks):
 C:\DMD\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(320): Error: tuple
 index 2 exceeds 2

 I've reversed the order, put types before identifiers and this works fine
 then:

 Tuple!(int, "index", double, "sum") t = tuple(1, 3.14);

 I'm not sure what you mean by "t has .first and .second as members", I
 can't seem to access those. Maybe you meant t.index and t.sum as members?


 On Fri, Jul 30, 2010 at 12:11 PM, Philippe Sigaud <
 philippe.sigaud gmail.com> wrote:

 On Thu, Jul 29, 2010 at 23:28, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 How do I print out an expanded tuple but with spaces between the values?
 There's this example on page 164:

 import std.typecons, std.stdio;

 void fun(T...)(T args) {
     // create a tuple to pack all arguments together
     gun(tuple(args));
 }

 void gun(T)(T value) {
     // expand the tuple back
     writeln(value.expand);
 }

 void main() {
     fun(1);
     fun(1, 2.2);
 }

 This prints out:
 1
 12.2

 But that's confusing, since the values are "glued" together when printed
 out. I really want to print out:
 1
 1 2.2

 Any ideas?

You can iterate on the values and create the corresponding string. Note that you must have a polymorphic function to map on a tuple's elements. void gun(T)(T value) { string result; foreach(index, Type; value.expand) { result ~= to!string(value.expand[i]) ~ " "; } writeln(result); } There will be a surnumerary " " at the very end, but I prefer to show the way to iterate on a tuple. value is a std.typecons.Tuple, but value.expand gives access to the raw (T...) tuple inside it.
 One other thing. I can use the .length property for value and parameter
 tuples, but only if I haven't built them myself with the call to
 std.typecons.tuple(). For example I can call writeln(T.length) in the fun()
 function (where the compiler automatically constructs a tuple), but not in
 the gun() function. So there seems to be compiler tuples and
 user-constructed tuples, which are not the same.

Yes, std.typecons.Tuple should have a length, it's trivial to add. It's issue #4381 http://d.puremagic.com/issues/show_bug.cgi?id=4381 And yes, there are 'raw', compiler-managed tuples which are lists of types and values 'glued' together. They are powerful, iterable, indexable, slicable, know their length, etc. They may even be assignable. Ah, in fact, they can hold anything that can be passed as a template argument, I guess. But, being a bunch of many different types, they cannot be returned by a function. That's C inheritance for you. They have no .init value neither, which I found too bad for generic code. http://d.puremagic.com/issues/show_bug.cgi?id=4536 So std.typecons.Tuple provides a way to wrap values inside a struct, while giving access to the types and values, and that can be returned by a function. It can also have named members, which can be quite handy when you return many things from a function, grouped inside a tuple. Tuple!("index", int, "sum", double) t = tuple(1,3.14); assert(t.index== 1); // t has .first and .second as members. assert(t.sum== 3.14);
 It's a bit of a shame that there isn't a chapter on tuples except this
 brief mention (I don't see it listed in the contents page). I guess I'll
 take a look at the implementation.

is!) in flux while he was writing this. D the language will not change much for some time, while the standard library is being actively transformed, if only to take into account the new features that were added for the past 6 months. btw, I like you posts, but do not always have the time to answer them. If among the numerous issues you posted there there is still one that bother you, do not hesitate to ask again for an answer. Philippe


--0016e6d9a3302ae602048c9f5d0e Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br>I&#39;ve found that the syntax mytuple.field[] can be used, I think thi= s is probably what you meant by .first and .second. <br><br><br><div class= =3D"gmail_quote">On Fri, Jul 30, 2010 at 8:20 PM, Andrej Mitrovic <span dir= =3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andrej.mitrovich= gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Hey, just tried o= ut your code.<br><br>In the first one there&#39;s a little typo (used &#39;= i&#39; instead of index), but that&#39;s ok. ;p<br> <br>It seems like I don&#39;t need to use the to!() template. This code see= ms to work fine:<div class=3D"im"><br> <br>void gun(T)(T value) {<br></div>=A0=A0=A0 foreach(Type; value.expand)<b= r>=A0=A0=A0=A0=A0=A0=A0 write(Type, &quot; &quot;);<br>=A0=A0=A0 <br>=A0=A0= =A0 writeln();<br>}<br><br>But regardless, at least I now know how to trave= rse through my own tuples, so thanks for that one.<br> <br>In your second example:<div class=3D"im"><br><div><br></div><div>Tuple!= (&quot;index&quot;, int, &quot;sum&quot;, double) t =3D=20 tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // t has= =20 .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</div> <br></div>I get an error way deep in the library itself (this could call fo= r a better error message, methinks):<br>C:\DMD\dmd2\windows\bin\..\..\src\p= hobos\std\typecons.d(320): Error: tuple index 2 exceeds 2<br><br>I&#39;ve r= eversed the order, put types before identifiers and this works fine then:<b= r> <br>Tuple!(int, &quot;index&quot;, double, &quot;sum&quot;) t =3D tuple(1, = 3.14);<br><br>I&#39;m not sure what you mean by &quot;t has .first and .sec= ond as members&quot;, I can&#39;t seem to access those. Maybe you meant t.i= ndex and t.sum as members?<br> <br><br><div class=3D"gmail_quote"><div class=3D"im">On Fri, Jul 30, 2010 a= t 12:11 PM, Philippe Sigaud <span dir=3D"ltr">&lt;<a href=3D"mailto:philipp= e.sigaud gmail.com" target=3D"_blank">philippe.sigaud gmail.com</a>&gt;</sp= an> wrote:<br> </div><div><div></div><div class=3D"h5"><blockquote class=3D"gmail_quote" s= tyle=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204= ); padding-left: 1ex;"> <div class=3D"gmail_quote"><div>On Thu, Jul 29, 2010 at 23:28, Andrej Mitro= vic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com" tar= get=3D"_blank">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockqu= ote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: = 1px solid rgb(204, 204, 204); padding-left: 1ex;"> How do I print out an expanded tuple but with spaces between the values? Th= ere&#39;s this example on page 164:<br><br>import std.typecons, std.stdio;<= br><br>void fun(T...)(T args) {<br>=A0=A0=A0 // create a tuple to pack all = arguments together<br> =A0=A0=A0 gun(tuple(args));<br>}<br><br>void gun(T)(T value) {=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 <br>=A0=A0=A0 // exp= and the tuple back<br>=A0=A0=A0 writeln(value.expand);<br>}<br><br>void mai= n() {<br>=A0=A0=A0 fun(1);<br>=A0=A0=A0 fun(1, 2.2);<br>}<br><br>This print= s out:<br> 1<br>12.2<br><br>But that&#39;s confusing, since the values are &quot;glued= &quot; together when printed out. I really want to print out:<br>1<br>1 2.2= <br><br>Any ideas?<br></blockquote><div><br></div></div><div>You can iterat= e on the values and create the corresponding string. Note that you must hav= e a polymorphic function to map on a tuple&#39;s elements.</div> <div> <div><br></div><div>void gun(T)(T value)</div><div>{</div></div><div>=A0=A0= =A0string result;</div><div>=A0=A0 =A0foreach(index, Type; value.expand)</= div><div>=A0=A0 =A0{</div><div>=A0=A0 =A0 =A0 =A0result ~=3D to!string(valu= e.expand[i]) ~ &quot; =A0&quot;;</div> <div>=A0=A0 =A0}</div><div>=A0=A0 =A0writeln(result);</div><div>}</div><div=
<br></div><div>There will be a surnumerary &quot; &quot; at the very end, =

.Tuple, but value.expand gives access to the raw (T...) tuple inside it.</d= iv> <div> <div><br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"mar= gin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-= left: 1ex;"><br>One other thing. I can use the .length property for value a= nd parameter tuples, but only if I haven&#39;t built them myself with the c= all to std.typecons.tuple(). For example I can call writeln(T.length) in th= e fun() function (where the compiler automatically constructs a tuple), but= not in the gun() function. So there seems to be compiler tuples and user-c= onstructed tuples, which are not the same. <br> </blockquote><div><br></div></div><div>Yes, std.typecons.Tuple should have = a length, it&#39;s trivial to add. It&#39;s issue #4381</div><div><br></div=
<div><a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4381" targ=


<div><br></div><div>And yes, there are &#39;raw&#39;, compiler-managed tupl= es which are lists of types and values &#39;glued&#39; together. They are p= owerful, iterable, indexable, slicable, know their length, etc. They may ev= en be assignable. Ah, in fact, they can hold anything that can be passed as= a template argument, I guess.</div> <div>But, being a bunch of many different types, they cannot be returned by= a function. That&#39;s C inheritance for you. They have no .init value nei= ther, which I found too bad for generic code.</div><div><br></div><div> <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4536" target=3D"= _blank">http://d.puremagic.com/issues/show_bug.cgi?id=3D4536</a></div><div>= <br></div><div>So std.typecons.Tuple provides a way to wrap values inside a= struct, while giving access to the types and values, and that can be retur= ned by a function. It can also have named members, which can be quite handy= when you return many things from a function, grouped inside a tuple.</div> <div><br></div><div>Tuple!(&quot;index&quot;, int, &quot;sum&quot;, double)= t =3D tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // = t has .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</d= iv><div> <div> <br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: = 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left:= 1ex;"> <br>It&#39;s a bit of a shame that there isn&#39;t a chapter on tuples exce= pt this brief mention (I don&#39;t see it listed in the contents page). I g= uess I&#39;ll take a look at the implementation.<div><div></div><div> <br></div></div></blockquote><div><br></div></div><div>Andrei didn&#39;t wa= nt to talk too much about Phobos, as it was (ans still is!) in flux while h= e was writing this. D the language will not change much for some time, whil= e the standard library is being actively transformed, if only to take into = account the new features that were added for the past 6 months.</div> <div><br></div><div>btw, I like you posts, but do not always have the time = to answer them. If among the numerous issues you posted there there is stil= l one that bother you, do not hesitate to ask again for an answer.</div> <div><br></div><font color=3D"#888888"><div>=A0Philippe</div></font></div> </blockquote></div></div></div><br> </blockquote></div><br> --0016e6d9a3302ae602048c9f5d0e--
Jul 30 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--001636833c0a2edba2048c9f671f
Content-Type: text/plain; charset=ISO-8859-1

Speaking of which, I think there's a typo in Phobos docs:

http://www.digitalmars.com/d/2.0/phobos/std_typecons.html

Tuple!(int, int) point;
// assign coordinates
point.field[0] = 5;
point.field[1] = 6;
// read coordinates
auto x = point.field[0];
auto y = point.[1];

The last one should be "auto y = point.field[1]"

On Fri, Jul 30, 2010 at 8:53 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 I've found that the syntax mytuple.field[] can be used, I think this is
 probably what you meant by .first and .second.


 On Fri, Jul 30, 2010 at 8:20 PM, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 Hey, just tried out your code.

 In the first one there's a little typo (used 'i' instead of index), but
 that's ok. ;p

 It seems like I don't need to use the to!() template. This code seems to
 work fine:


 void gun(T)(T value) {
     foreach(Type; value.expand)
         write(Type, " ");

     writeln();
 }

 But regardless, at least I now know how to traverse through my own tuples,
 so thanks for that one.

 In your second example:


 Tuple!("index", int, "sum", double) t = tuple(1,3.14);

 assert(t.index== 1); // t has .first and .second as members.
 assert(t.sum== 3.14);

 I get an error way deep in the library itself (this could call for a
 better error message, methinks):
 C:\DMD\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(320): Error: tuple
 index 2 exceeds 2

 I've reversed the order, put types before identifiers and this works fine
 then:

 Tuple!(int, "index", double, "sum") t = tuple(1, 3.14);

 I'm not sure what you mean by "t has .first and .second as members", I
 can't seem to access those. Maybe you meant t.index and t.sum as members?


 On Fri, Jul 30, 2010 at 12:11 PM, Philippe Sigaud <
 philippe.sigaud gmail.com> wrote:

 On Thu, Jul 29, 2010 at 23:28, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 How do I print out an expanded tuple but with spaces between the values?
 There's this example on page 164:

 import std.typecons, std.stdio;

 void fun(T...)(T args) {
     // create a tuple to pack all arguments together
     gun(tuple(args));
 }

 void gun(T)(T value) {
     // expand the tuple back
     writeln(value.expand);
 }

 void main() {
     fun(1);
     fun(1, 2.2);
 }

 This prints out:
 1
 12.2

 But that's confusing, since the values are "glued" together when printed
 out. I really want to print out:
 1
 1 2.2

 Any ideas?

You can iterate on the values and create the corresponding string. Note that you must have a polymorphic function to map on a tuple's elements. void gun(T)(T value) { string result; foreach(index, Type; value.expand) { result ~= to!string(value.expand[i]) ~ " "; } writeln(result); } There will be a surnumerary " " at the very end, but I prefer to show the way to iterate on a tuple. value is a std.typecons.Tuple, but value.expand gives access to the raw (T...) tuple inside it.
 One other thing. I can use the .length property for value and parameter
 tuples, but only if I haven't built them myself with the call to
 std.typecons.tuple(). For example I can call writeln(T.length) in the fun()
 function (where the compiler automatically constructs a tuple), but not in
 the gun() function. So there seems to be compiler tuples and
 user-constructed tuples, which are not the same.

Yes, std.typecons.Tuple should have a length, it's trivial to add. It's issue #4381 http://d.puremagic.com/issues/show_bug.cgi?id=4381 And yes, there are 'raw', compiler-managed tuples which are lists of types and values 'glued' together. They are powerful, iterable, indexable, slicable, know their length, etc. They may even be assignable. Ah, in fact, they can hold anything that can be passed as a template argument, I guess. But, being a bunch of many different types, they cannot be returned by a function. That's C inheritance for you. They have no .init value neither, which I found too bad for generic code. http://d.puremagic.com/issues/show_bug.cgi?id=4536 So std.typecons.Tuple provides a way to wrap values inside a struct, while giving access to the types and values, and that can be returned by a function. It can also have named members, which can be quite handy when you return many things from a function, grouped inside a tuple. Tuple!("index", int, "sum", double) t = tuple(1,3.14); assert(t.index== 1); // t has .first and .second as members. assert(t.sum== 3.14);
 It's a bit of a shame that there isn't a chapter on tuples except this
 brief mention (I don't see it listed in the contents page). I guess I'll
 take a look at the implementation.

is!) in flux while he was writing this. D the language will not change much for some time, while the standard library is being actively transformed, if only to take into account the new features that were added for the past 6 months. btw, I like you posts, but do not always have the time to answer them. If among the numerous issues you posted there there is still one that bother you, do not hesitate to ask again for an answer. Philippe



--001636833c0a2edba2048c9f671f Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Speaking of which, I think there&#39;s a typo in Phobos docs:<br><br><a hre= f=3D"http://www.digitalmars.com/d/2.0/phobos/std_typecons.html">http://www.= digitalmars.com/d/2.0/phobos/std_typecons.html</a><br><pre class=3D"d_code"=

, <span class=3D"d_keyword">int</span>) point;<br><span class=3D"d_comment=

=3D 6;<br> <span class=3D"d_comment">// read coordinates<br></span><span class=3D"d_ke= yword">auto</span> x =3D point.field[0];<br><span class=3D"d_keyword">auto<= /span> y =3D point.[1];</pre>The last one should be &quot;auto y =3D point.= field[1]&quot;<br> <br><div class=3D"gmail_quote">On Fri, Jul 30, 2010 at 8:53 PM, Andrej Mitr= ovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">an= drej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmai= l_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204= , 204, 204); padding-left: 1ex;"> <br>I&#39;ve found that the syntax mytuple.field[] can be used, I think thi= s is probably what you meant by .first and .second. <br><div><div></div><di= v class=3D"h5"><br><br><div class=3D"gmail_quote">On Fri, Jul 30, 2010 at 8= :20 PM, Andrej Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitr= ovich gmail.com" target=3D"_blank">andrej.mitrovich gmail.com</a>&gt;</span=
 wrote:<br>

<blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">Hey, just tried o= ut your code.<br><br>In the first one there&#39;s a little typo (used &#39;= i&#39; instead of index), but that&#39;s ok. ;p<br> <br>It seems like I don&#39;t need to use the to!() template. This code see= ms to work fine:<div><br> <br>void gun(T)(T value) {<br></div>=A0=A0=A0 foreach(Type; value.expand)<b= r>=A0=A0=A0=A0=A0=A0=A0 write(Type, &quot; &quot;);<br>=A0=A0=A0 <br>=A0=A0= =A0 writeln();<br>}<br><br>But regardless, at least I now know how to trave= rse through my own tuples, so thanks for that one.<br> <br>In your second example:<div><br><div><br></div><div>Tuple!(&quot;index&= quot;, int, &quot;sum&quot;, double) t =3D=20 tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // t has= =20 .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</div> <br></div>I get an error way deep in the library itself (this could call fo= r a better error message, methinks):<br>C:\DMD\dmd2\windows\bin\..\..\src\p= hobos\std\typecons.d(320): Error: tuple index 2 exceeds 2<br><br>I&#39;ve r= eversed the order, put types before identifiers and this works fine then:<b= r> <br>Tuple!(int, &quot;index&quot;, double, &quot;sum&quot;) t =3D tuple(1, = 3.14);<br><br>I&#39;m not sure what you mean by &quot;t has .first and .sec= ond as members&quot;, I can&#39;t seem to access those. Maybe you meant t.i= ndex and t.sum as members?<br> <br><br><div class=3D"gmail_quote"><div>On Fri, Jul 30, 2010 at 12:11 PM, P= hilippe Sigaud <span dir=3D"ltr">&lt;<a href=3D"mailto:philippe.sigaud gmai= l.com" target=3D"_blank">philippe.sigaud gmail.com</a>&gt;</span> wrote:<br=

n: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-le= ft: 1ex;"> <div class=3D"gmail_quote"><div>On Thu, Jul 29, 2010 at 23:28, Andrej Mitro= vic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com" tar= get=3D"_blank">andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockqu= ote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: = 1px solid rgb(204, 204, 204); padding-left: 1ex;"> How do I print out an expanded tuple but with spaces between the values? Th= ere&#39;s this example on page 164:<br><br>import std.typecons, std.stdio;<= br><br>void fun(T...)(T args) {<br>=A0=A0=A0 // create a tuple to pack all = arguments together<br> =A0=A0=A0 gun(tuple(args));<br>}<br><br>void gun(T)(T value) {=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 <br>=A0=A0=A0 // exp= and the tuple back<br>=A0=A0=A0 writeln(value.expand);<br>}<br><br>void mai= n() {<br>=A0=A0=A0 fun(1);<br>=A0=A0=A0 fun(1, 2.2);<br>}<br><br>This print= s out:<br> 1<br>12.2<br><br>But that&#39;s confusing, since the values are &quot;glued= &quot; together when printed out. I really want to print out:<br>1<br>1 2.2= <br><br>Any ideas?<br></blockquote><div><br></div></div><div>You can iterat= e on the values and create the corresponding string. Note that you must hav= e a polymorphic function to map on a tuple&#39;s elements.</div> <div> <div><br></div><div>void gun(T)(T value)</div><div>{</div></div><div>=A0=A0= =A0string result;</div><div>=A0=A0 =A0foreach(index, Type; value.expand)</= div><div>=A0=A0 =A0{</div><div>=A0=A0 =A0 =A0 =A0result ~=3D to!string(valu= e.expand[i]) ~ &quot; =A0&quot;;</div> <div>=A0=A0 =A0}</div><div>=A0=A0 =A0writeln(result);</div><div>}</div><div=
<br></div><div>There will be a surnumerary &quot; &quot; at the very end, =

.Tuple, but value.expand gives access to the raw (T...) tuple inside it.</d= iv> <div> <div><br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"mar= gin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-= left: 1ex;"><br>One other thing. I can use the .length property for value a= nd parameter tuples, but only if I haven&#39;t built them myself with the c= all to std.typecons.tuple(). For example I can call writeln(T.length) in th= e fun() function (where the compiler automatically constructs a tuple), but= not in the gun() function. So there seems to be compiler tuples and user-c= onstructed tuples, which are not the same. <br> </blockquote><div><br></div></div><div>Yes, std.typecons.Tuple should have = a length, it&#39;s trivial to add. It&#39;s issue #4381</div><div><br></div=
<div><a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4381" targ=


<div><br></div><div>And yes, there are &#39;raw&#39;, compiler-managed tupl= es which are lists of types and values &#39;glued&#39; together. They are p= owerful, iterable, indexable, slicable, know their length, etc. They may ev= en be assignable. Ah, in fact, they can hold anything that can be passed as= a template argument, I guess.</div> <div>But, being a bunch of many different types, they cannot be returned by= a function. That&#39;s C inheritance for you. They have no .init value nei= ther, which I found too bad for generic code.</div><div><br></div><div> <a href=3D"http://d.puremagic.com/issues/show_bug.cgi?id=3D4536" target=3D"= _blank">http://d.puremagic.com/issues/show_bug.cgi?id=3D4536</a></div><div>= <br></div><div>So std.typecons.Tuple provides a way to wrap values inside a= struct, while giving access to the types and values, and that can be retur= ned by a function. It can also have named members, which can be quite handy= when you return many things from a function, grouped inside a tuple.</div> <div><br></div><div>Tuple!(&quot;index&quot;, int, &quot;sum&quot;, double)= t =3D tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // = t has .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</d= iv><div> <div> <br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: = 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left:= 1ex;"> <br>It&#39;s a bit of a shame that there isn&#39;t a chapter on tuples exce= pt this brief mention (I don&#39;t see it listed in the contents page). I g= uess I&#39;ll take a look at the implementation.<div><div></div><div> <br></div></div></blockquote><div><br></div></div><div>Andrei didn&#39;t wa= nt to talk too much about Phobos, as it was (ans still is!) in flux while h= e was writing this. D the language will not change much for some time, whil= e the standard library is being actively transformed, if only to take into = account the new features that were added for the past 6 months.</div> <div><br></div><div>btw, I like you posts, but do not always have the time = to answer them. If among the numerous issues you posted there there is stil= l one that bother you, do not hesitate to ask again for an answer.</div> <div><br></div><font color=3D"#888888"><div>=A0Philippe</div></font></div> </blockquote></div></div></div><br> </blockquote></div><br> </div></div></blockquote></div><br> --001636833c0a2edba2048c9f671f--
Jul 30 2010
prev sibling next sibling parent Brad Roberts <braddr puremagic.com> writes:
On Fri, 30 Jul 2010, Andrej Mitrovic wrote:

 Speaking of which, I think there's a typo in Phobos docs:
 
 http://www.digitalmars.com/d/2.0/phobos/std_typecons.html
 
 Tuple!(int, int) point;
 // assign coordinates
 point.field[0] = 5;
 point.field[1] = 6;
 // read coordinates
 auto x = point.field[0];
 auto y = point.[1];
 
 The last one should be "auto y = point.field[1]"

Fix submitted to svn.
Jul 30 2010
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--00151750e9bed94354048ca0a3f0
Content-Type: text/plain; charset=ISO-8859-1

On Fri, Jul 30, 2010 at 20:20, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

 Hey, just tried out your code.

 In the first one there's a little typo (used 'i' instead of index), but
 that's ok. ;p

Ah yes, that was typed over the course of 2-3 hours, with my children jumping around :)
 It seems like I don't need to use the to!() template. This code seems to
 work fine:


 void gun(T)(T value) {
     foreach(Type; value.expand)
         write(Type, " ");

     writeln();
 }

a name, as you're directly iterating on the values. Sorry, my mistake: I'm so used to iterate on typetuples, where the iteration is done on a index-Type pair that I typed that without thinking.
 But regardless, at least I now know how to traverse through my own tuples,
 so thanks for that one.

As I said, value.expand is an instantiated typetuple, to it's iterable, indexed with [i], can be sliced with [i..j], it knows its length, etc. Very powerful stuff, very easy to use. None of the gobbledygook from C++. Note that .field and .expand are aliases, they are the same access to the tuple's fields, under a different name.
 In your second example:


 Tuple!("index", int, "sum", double) t = tuple(1,3.14);

 assert(t.index== 1); // t has .first and .second as members.
 assert(t.sum== 3.14);

 I get an error way deep in the library itself (this could call for a better
 error message, methinks):
 C:\DMD\dmd2\windows\bin\..\..\src\phobos\std\typecons.d(320): Error: tuple
 index 2 exceeds 2

 I've reversed the order, put types before identifiers and this works fine
 then:

 Tuple!(int, "index", double, "sum") t = tuple(1, 3.14);

Sorry also, I should have checked typecons docs.
 I'm not sure what you mean by "t has .first and .second as members", I
 can't seem to access those. Maybe you meant t.index and t.sum as members?

Hem, as I said, I typed the mail over a few hours, the first version of the tuple was Tuple!((int, "first", double, "second"), but I found first and second a bit bland, so I changed that to .index and .sum. Man, I made a mess of my explanation. I'm glad you still understood something :) --00151750e9bed94354048ca0a3f0 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Fri, Jul 30, 2010 at 20:20, Andrej Mi= trovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">= andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gm= ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le= ft:1ex;"> Hey, just tried out your code.<br><br>In the first one there&#39;s a little= typo (used &#39;i&#39; instead of index), but that&#39;s ok. ;p<br></block= quote><div><br></div><div>Ah yes, that was typed over the course of 2-3 hou= rs, with my children jumping around :)</div> <div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;= border-left:1px #ccc solid;padding-left:1ex;"><br>It seems like I don&#39;t= need to use the to!() template. This code seems to work fine:<div class=3D= "im"> <br> <br>void gun(T)(T value) {<br></div>=A0=A0=A0 foreach(Type; value.expand)<b= r>=A0=A0=A0=A0=A0=A0=A0 write(Type, &quot; &quot;);<br>=A0=A0=A0 <br>=A0=A0= =A0 writeln();<br>}<br><br></blockquote><div><br></div><div>If you just wan= t to print them, yes. In that case btw, do not use &#39;Type&#39; as a name= , as you&#39;re directly iterating on the values. Sorry, my mistake: I&#39;= m so used to iterate on typetuples, where the iteration is done on a index-= Type pair that I typed that without thinking.</div> <div><br></div><div>=A0</div><blockquote class=3D"gmail_quote" style=3D"mar= gin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">But regardless= , at least I now know how to traverse through my own tuples, so thanks for = that one.<br> </blockquote><div><br></div><div>As I said, value.expand is an instantiated= typetuple, to it&#39;s iterable, indexed with [i], can be sliced with [i..= j], it knows its length, etc. Very powerful stuff, very easy to use. None o= f the gobbledygook from C++.</div> <div><br></div><div>Note that .field and .expand are aliases, they are the = same access to the tuple&#39;s fields, under a different name.</div><div>= =A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;borde= r-left:1px #ccc solid;padding-left:1ex;"> <br>In your second example:<div class=3D"im"><br><div><br></div><div>Tuple!= (&quot;index&quot;, int, &quot;sum&quot;, double) t =3D=20 tuple(1,3.14);</div><div><br></div><div>assert(t.index=3D=3D 1); // t has= =20 .first and .second as members.</div><div>assert(t.sum=3D=3D 3.14);</div> <br></div>I get an error way deep in the library itself (this could call fo= r a better error message, methinks):<br>C:\DMD\dmd2\windows\bin\..\..\src\p= hobos\std\typecons.d(320): Error: tuple index 2 exceeds 2<br><br>I&#39;ve r= eversed the order, put types before identifiers and this works fine then:<b= r> <br>Tuple!(int, &quot;index&quot;, double, &quot;sum&quot;) t =3D tuple(1, = 3.14);<br></blockquote><div><br></div><div>Sorry also, I should have checke= d typecons docs.</div><div><br></div><div>=A0</div><blockquote class=3D"gma= il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef= t:1ex;"> <br>I&#39;m not sure what you mean by &quot;t has .first and .second as mem= bers&quot;, I can&#39;t seem to access those. Maybe you meant t.index and t= .sum as members?<br></blockquote><div><br></div><div><br></div><div>Hem, as= I said, I typed the mail over a few hours, the first version of the tuple = was Tuple!((int, &quot;first&quot;, double, &quot;second&quot;), but I foun= d first and second a bit bland, so I changed that to .index and .sum.</div> <div><br></div><div>Man, I made a mess of my explanation. I&#39;m glad you = still understood something :)</div><div><br></div><div><br></div><div><br><= /div></div> --00151750e9bed94354048ca0a3f0--
Jul 30 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016363ba32a23aedd048c7568e1
Content-Type: text/plain; charset=ISO-8859-1

It was adequate for the first function, but I never knew why you've changed
"== bool" to ": bool", and why you're using slices in the second templated
function. Philippe explained it in more detail so I'm starting to get it.

Otherwise, the only issue left is the float vs double comparisons.

For this unittest:
    double[] d1 = [6.0, 1.5, 2.4, 3];
    float[] d2 = [1.5, 2.4];
    assert(find(d1, d2) == d1[1 .. $]);

Inside the second template function I've added a writeln, and I can see the
if statement evaluates "[1.5, 2.4] == [1.5, 2.4]" to false and will not
break out of the loop. I don't know whether this is a DMD bug or if "float[]
d2" should be changed to "double[] d2" in TDPL, since that runs fine. IIRC
arrays are value types and as such they are compared bit-by-bit to each
other, right? And since doubles and floats have different sizes, that
unittest then fails.


On Wed, Jul 28, 2010 at 6:19 PM, Andrei Alexandrescu <
SeeWebsiteForEmail erdani.org> wrote:

 Andrej Mitrovic wrote:

 Also, Andrei, you never explained the if(is()) signature of the second
 templated function. I hope to get some pointers on that. :)

Is the explanation on page 141 adequate? Andrei

--0016363ba32a23aedd048c7568e1 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable It was adequate for the first function, but I never knew why you&#39;ve cha= nged &quot;=3D=3D bool&quot; to &quot;: bool&quot;, and why you&#39;re usin= g slices in the second templated function. Philippe explained it in more de= tail so I&#39;m starting to get it. <br> <br>Otherwise, the only issue left is the float vs double comparisons. <br>= <br>For this unittest:<br>=A0=A0=A0 double[] d1 =3D [6.0, 1.5, 2.4, 3];<br>= =A0=A0=A0 float[] d2 =3D [1.5, 2.4];<br>=A0=A0=A0 assert(find(d1, d2) =3D= =3D d1[1 .. $]);<br><br> Inside the second template function I&#39;ve added a writeln, and I can see= the if statement evaluates &quot;[1.5, 2.4] =3D=3D [1.5, 2.4]&quot; to fal= se and will not break out of the loop. I don&#39;t know whether this is a D= MD bug or if &quot;float[] d2&quot; should be changed to &quot;double[] d2&= quot; in TDPL, since that runs fine. IIRC arrays are value types and as suc= h they are compared bit-by-bit to each other, right? And since doubles and = floats have different sizes, that unittest then fails. <br> <br><br><div class=3D"gmail_quote">On Wed, Jul 28, 2010 at 6:19 PM, Andrei = Alexandrescu <span dir=3D"ltr">&lt;<a href=3D"mailto:SeeWebsiteForEmail erd= ani.org">SeeWebsiteForEmail erdani.org</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 class=3D"im">Andrej Mitrovic wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> Also, Andrei, you never explained the if(is()) signature of the second temp= lated function. I hope to get some pointers on that. :)<br> </blockquote> <br></div> Is the explanation on page 141 adequate?<br><font color=3D"#888888"> <br> Andrei<br> </font></blockquote></div><br> --0016363ba32a23aedd048c7568e1--
Jul 28 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--000e0cd402c42b9425048ca0a851
Content-Type: text/plain; charset=ISO-8859-1

Okay take a look at this:

import std.stdio;

void main()
{
}

T[] find(T, E)(T[] haystack, E needle)
    if (is(typeof(haystack[0] != needle) == bool))
{
    while (haystack.length > 0 && haystack[0] != needle) {
        haystack = haystack[1 .. $];
    }
    return haystack;
}


T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (is(typeof(longer[0 .. 1] == shorter) : bool) && false)
{
    while (longer.length >= shorter.length) {
        if (longer[0 .. shorter.length] == shorter)
            break;
        longer = longer[1 .. $];
    }
    return longer;
}

unittest {
    string[] longer = ["one", "two"];
    string shorter = "two";
    find(longer, shorter);

    writeln(is(typeof(longer[0 .. 1] == shorter) : bool) && false); //
writes false
}

I'm tyring to make the code in the unittest use the first templated
function. But it will fail because DMD matches the call to find to the
second templated function. But it should never match the second template,
I've forced it's constraint to always evaluate to false.

The writeln() in the unittest has the copy of the constraint expression and
it does evaluate to false. If I comment out the second template, this code
will compile as DMD will match the first template.

I'm using this forced "&& false" expression because I was trying out all
sorts of type/value expressions but they never worked for me.

Anyways, I'd appreciate any help here. :)




On Wed, Jul 28, 2010 at 5:22 PM, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 These templates seem to be hard to get right. I guess with experience they
 get easier to write and comprehend. Anyways, thanks for the explanation.


 On Wed, Jul 28, 2010 at 4:44 PM, Philippe Sigaud <
 philippe.sigaud gmail.com> wrote:

 On Wed, Jul 28, 2010 at 05:50, Andrej Mitrovic <
 andrej.mitrovich gmail.com> wrote:

 I won't comment on the double/float issue, I do not anything about it.


 T[] find(T, E)(T[] haystack, E needle)
    if (is(typeof(haystack[0] != needle) == bool))

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (is(typeof(longer[0 .. 1] == shorter) : bool))

 Also, Andrei, you never explained the if(is()) signature of the second
 templated function. I hope to get some pointers on that. :)

I'll have a try at this one. As you may know, the is(typeof()) syntax is a way to try to compile an expression and see if it works. If it works, it has a type, given by typeof and is(Type) returns true. So the first one is really saying: "Hey compiler, may I compare an element of haystack (of type T) with an E In this case, longer is an array. So longer[0] would be an element, a T1. There is no chance that shorter will match as an element cannot be equal to an array ... except, of course, if longer is an array of T2[] (T1 == T2[]). Longer is a T2[][]. That may happen for arrays of strings, strings being arrays of chars. And I think that's the problem you have in your last unit test. Anyway, he takes longer[0..1] to get a slice, which is a dynamic array, a T1[] and hence comparable to a T2[]... most of the time. As for using ': bool' instead of '== bool' as in the first find(), I don't think there is any difference in this case. I understand T == U as 'T is the exact same type as U', whereas T : U is for me "T is a subtype of U". But then, a subtype of bool is pretty much constrained to be a bool. The T : U syntax is pretty much only used for classes : if(is(T : MyClass)) is saying : 'compile this only if T is a subclass of MyClass'. Philippe , except if longer is in fact


--000e0cd402c42b9425048ca0a851 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Okay take a look at this:<br><br>import std.stdio;<br><br>void main()<br>{<= br>}<br><br>T[] find(T, E)(T[] haystack, E needle)<br>=A0=A0=A0 if (is(type= of(haystack[0] !=3D needle) =3D=3D bool))<br>{<br>=A0=A0=A0 while (haystack= .length &gt; 0 &amp;&amp; haystack[0] !=3D needle) {<br> =A0=A0=A0=A0=A0=A0=A0 haystack =3D haystack[1 .. $];<br>=A0=A0=A0 }<br>=A0= =A0=A0 return haystack;<br>}<br><br><br>T1[] find(T1, T2)(T1[] longer, T2[]= shorter)<br>=A0=A0=A0 if (is(typeof(longer[0 .. 1] =3D=3D shorter) : bool)= &amp;&amp; false)<br>{<br>=A0=A0=A0 while (longer.length &gt;=3D shorter.l= ength) {<br> =A0=A0=A0=A0=A0=A0=A0 if (longer[0 .. shorter.length] =3D=3D shorter)<br>= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 longer = =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br>}<br><br>= unittest {<br>=A0=A0=A0 string[] longer =3D [&quot;one&quot;, &quot;two&quo= t;];<br> =A0=A0=A0 string shorter =3D &quot;two&quot;;<br>=A0=A0=A0 find(longer, sho= rter);<br>=A0=A0=A0 <br>=A0=A0=A0 writeln(is(typeof(longer[0 .. 1] =3D=3D s= horter) : bool) &amp;&amp; false); // writes false<br>}<br><br>I&#39;m tyri= ng to make the code in the unittest use the first templated function. But i= t will fail because DMD matches the call to find to the second templated fu= nction. But it should never match the second template, I&#39;ve forced it&#= 39;s constraint to always evaluate to false. <br> <br>The writeln() in the unittest has the copy of the constraint expression= and it does evaluate to false. If I comment out the second template, this = code will compile as DMD will match the first template.<br><br>I&#39;m usin= g this forced &quot;&amp;&amp; false&quot; expression because I was trying = out all sorts of type/value expressions but they never worked for me.<br> <br>Anyways, I&#39;d appreciate any help here. :)<br><br><br><br><br><div c= lass=3D"gmail_quote">On Wed, Jul 28, 2010 at 5:22 PM, Andrej Mitrovic <span= dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andrej.mitro= vich gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">These templates s= eem to be hard to get right. I guess with experience they get easier to wri= te and comprehend. Anyways, thanks for the explanation.<div> <div></div><div class=3D"h5"><br><br><div class=3D"gmail_quote">On Wed, Jul= 28, 2010 at 4:44 PM, Philippe Sigaud <span dir=3D"ltr">&lt;<a href=3D"mail= to:philippe.sigaud gmail.com" target=3D"_blank">philippe.sigaud gmail.com</= a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div class=3D"gma= il_quote">On Wed, Jul 28, 2010 at 05:50, Andrej Mitrovic <span dir=3D"ltr">= &lt;<a href=3D"mailto:andrej.mitrovich gmail.com" target=3D"_blank">andrej.= mitrovich gmail.com</a>&gt;</span> wrote:<br> <div><br></div><div>I won&#39;t comment on the double/float issue, I do not= anything about it.</div> <div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0p= t 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><di= v>T[] find(T, E)(T[] haystack, E needle)<br> =A0 =A0if (is(typeof(haystack[0] !=3D needle) =3D=3D bool))<br><br></div><= div> T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br> =A0 =A0if (is(typeof(longer[0 .. 1] =3D=3D shorter) : bool))<br><br></div>= <div> Also, Andrei, you never explained the if(is()) signature of the second temp= lated function. I hope to get some pointers on that. :)<br> </div></blockquote></div><div><br></div>I&#39;ll have a try at this one.<di= v>As you may know, the is(typeof()) syntax is a way to try to compile an ex= pression and see if it works. If it works, it has a type, given by typeof a= nd is(Type) returns true. So the first one is really saying: &quot;Hey comp= iler, may I compare an element of haystack (of type T) with an E</div> <div>In this case,=A0longer is an array. So longer[0] would be an element, = a T1. There is no chance that shorter will match as an element cannot be eq= ual to an array ... except, of course, if longer is an array of T2[] =A0(T1= =3D=3D T2[]). Longer is a T2[][]. That may happen for arrays of strings, s= trings being arrays of chars. And I think that&#39;s the problem you have i= n your last unit test.<div> <br></div><div>Anyway,=A0he takes longer[0..1] to get a slice, which is a d= ynamic array, a T1[] and hence comparable to a T2[]... most of the time.</d= iv><div><br></div><div>As for using &#39;: bool&#39; instead of &#39;=3D=3D= bool&#39; as in the first find(), =A0I don&#39;t think there is any differ= ence in this case. I understand T =3D=3D U as &#39;T is the exact same type= as U&#39;, whereas T : U is for me &quot;T is a subtype of U&quot;. But th= en, a subtype of bool is pretty much constrained to be a bool. The T : U sy= ntax is pretty much only used for classes : if(is(T : MyClass)) is saying := &#39;compile this only if T is a subclass of MyClass&#39;.</div> <div><br></div><div><br></div><div>Philippe</div><div><br></div><div><br></= div><div><br></div><div>, except if longer is in fact</div></div> </blockquote></div><br> </div></div></blockquote></div><br> --000e0cd402c42b9425048ca0a851--
Jul 30 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--000e0cd5bee6863373048ca20863
Content-Type: text/plain; charset=ISO-8859-1

First,  trying a copy-paste of your code gives me an error in object.di
(DMD 2.047 on Windows)

C:\dmd\windows\bin\..\..\src\druntime\import\object.di|487|Error:
incompatible types for ((a) != (a2[i])): 'string' and 'immutable(char)'|
||=== Build finished: 1 errors, 0 warnings ===|

And Code::Blocks jumps me to object.di:

bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
{
    if (a1.length != a2.length)
return false;
    foreach(i, a; a1)
    { if (a != a2[i]) // <-- line 487. Uh oh, trying to compare strings and
chars
    return false;
    }
    return true;
}

I had to modify it:

bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
if (is(typeof(T1.init != T2.init))) // Are T1 and T2 comparable? If not, do
not bother to compile
{
   if (a1.length != a2.length) return false;
    foreach(i, a; a1)
    { if (a != a2[i])
        return false;
    }
    return true;
}

Another possibility would have it return false, but in that case, array
comparisons always compile and we lose the ability to use them as test for
instantiating a template.

I guess _ArrayEq is some internal called by the constraint, while doing the
comparison. Saving object.di and recompiling everything allows the templates
constraints to function and gives me a call to the first find.

Without the '&& false', it still calls the first find... because it still
cannot instantiate the second template:

The first find can be instantiated with T = immutable(char)[] and E =
immutable(char)[], there is nothing stopping it: T and E are the same type,
so they are trivially comparable. "two" is a valid target value for ["one",
"two"].
The second find would have T1 = immutable(char)[] and T2 = immutable(char)
and those do not compare.


testing it, find("one two three", "two") correctly calls the second version
and returns "two three".

So, maybe you just found a bug in object.di._ArrayEq. I'll post on the main
list. Anyway, for me, it seems to work, if I understand correctly what
you're doing.

Btw, if you find yourself using the same constraint regularly, you can
abstract it away in another template that returns (er, becomes, rather) a
boolean:

template areComparable(T1, T2)
{
   enum bool areComparable = is(typeof(T1.init == T2.init)); // eponymous
template trick
}

And then:

T[] find(T, E)(T[] haystack, E needle)
    if (areComparable!(T, E))
{
}


T[] find(T, E)(T[] longer, E[] shorter)
    if (areComparable!(T, E))

{
}

Which makes for cleaner code. I renamed T1 and T2 to T and E, so showcase
the difference between the two.


Philippe

--000e0cd5bee6863373048ca20863
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<div>First, =A0trying a copy-paste of your code gives me an error in object=
.di</div><div>(DMD 2.047 on Windows)</div><div><br></div><div>C:\dmd\window=
s\bin\..\..\src\druntime\import\object.di|487|Error: incompatible types for=
 ((a) !=3D (a2[i])): &#39;string&#39; and &#39;immutable(char)&#39;|</div>
<div>||=3D=3D=3D Build finished: 1 errors, 0 warnings =3D=3D=3D|</div><div>=
<br></div><div>And Code::Blocks jumps me to object.di:</div><div><br></div>=
<div>bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)</div><div>{</div><div>=A0=A0 =
=A0if (a1.length !=3D a2.length)</div>
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre">	</span>retur=
n false;</div><div>=A0=A0 =A0foreach(i, a; a1)</div><div>=A0=A0 =A0{<span c=
lass=3D"Apple-tab-span" style=3D"white-space:pre">	</span>if (a !=3D a2[i])=
 // &lt;-- line 487. Uh oh, trying to compare strings and chars</div>
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre">	</span> =A0 =
=A0return false;</div><div>=A0=A0 =A0}</div><div>=A0=A0 =A0return true;</di=
v><div>}</div><div><br></div><div>I had to modify it:</div><div><br></div><=
div>bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)=A0</div>
<div><span class=3D"Apple-tab-span" style=3D"white-space:pre">	</span>if (i=
s(typeof(T1.init !=3D T2.init))) // Are T1 and T2 comparable? If not, do no=
t bother to compile</div><div>{</div><div>=A0=A0 if (a1.length !=3D a2.leng=
th) return false;</div>
<div>=A0=A0 =A0foreach(i, a; a1)</div><div>=A0=A0 =A0{<span class=3D"Apple-=
tab-span" style=3D"white-space:pre">	</span>if (a !=3D a2[i])</div><div>=A0=
=A0 =A0 =A0 =A0return false;</div><div>=A0=A0 =A0}</div><div>=A0=A0 =A0retu=
rn true;</div><div>}</div><div><br></div>
<div>Another possibility would have it return false, but in that case, arra=
y comparisons always compile and we lose the ability to use them as test fo=
r instantiating a template.</div><div><br></div><div>I guess _ArrayEq is so=
me internal called by the constraint, while doing the comparison. Saving ob=
ject.di and recompiling everything allows the templates constraints to func=
tion and gives me a call to the first find.</div>
<div><br></div><div>Without the &#39;&amp;&amp; false&#39;, it still calls =
the first find... because it still cannot instantiate the second template:<=
/div><div><br></div><div>The first find can be instantiated with T =3D immu=
table(char)[] and E =3D immutable(char)[], there is nothing stopping it: T =
and E are the same type, so they are trivially comparable. &quot;two&quot; =
is a valid target value for [&quot;one&quot;, &quot;two&quot;].</div>
<div>The second find would have T1 =3D immutable(char)[] and T2 =3D immutab=
le(char) and those do not compare.</div><div><br></div><div><br></div><div>=
testing it, find(&quot;one two three&quot;, &quot;two&quot;) correctly call=
s the second version and returns &quot;two three&quot;.</div>
<div><br></div><div>So, maybe you just found a bug in object.di._ArrayEq. I=
&#39;ll post on the main list. Anyway, for me, it seems to work, if I under=
stand correctly what you&#39;re doing.</div><div><br></div><div>Btw, if you=
 find yourself using the same constraint regularly, you can abstract it awa=
y in another template that returns (er, becomes, rather) a boolean:</div>
<div><br></div><div>template areComparable(T1, T2)</div><div>{</div><div>=
=A0=A0 enum bool areComparable =3D is(typeof(T1.init =3D=3D T2.init)); // e=
ponymous template trick</div><div>}</div><div><br></div><div>And then:</div=
<div><br>

ns-serif; font-size: 12.5px; border-collapse: collapse; "><div class=3D"im"= style=3D"color: rgb(80, 0, 80); ">T[] find(T, E)(T[] haystack, E needle)<b= r>=A0=A0=A0 if (areComparable!(T, E))<br> </div><div class=3D"im" style=3D"color: rgb(80, 0, 80); ">{<br>}<br><br><br=
</div><div class=3D"im" style=3D"color: rgb(80, 0, 80); ">T[] find(T, E)(T=

ass=3D"im" style=3D"color: rgb(80, 0, 80); "> <br>{<br>}<br></div><div class=3D"im" style=3D"color: rgb(80, 0, 80); "><br=
</div><div class=3D"im" style=3D"color: rgb(80, 0, 80); ">Which makes for =

tween the two.</div> <div class=3D"im" style=3D"color: rgb(80, 0, 80); "><br></div><div class=3D= "im" style=3D"color: rgb(80, 0, 80); "><br></div><div class=3D"im" style=3D= "color: rgb(80, 0, 80); "><span class=3D"Apple-style-span" style=3D"font-si= ze: 12.5px; ">Philippe</span></div> <div class=3D"im" style=3D"color: rgb(80, 0, 80); "><br></div></span></div> --000e0cd5bee6863373048ca20863--
Jul 30 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016364d22e54f8a85048ca2cbf9
Content-Type: text/plain; charset=ISO-8859-1

On Sat, Jul 31, 2010 at 12:04 AM, Philippe Sigaud <philippe.sigaud gmail.com
 wrote:

 First,  trying a copy-paste of your code gives me an error in object.di
 (DMD 2.047 on Windows)

 C:\dmd\windows\bin\..\..\src\druntime\import\object.di|487|Error:
 incompatible types for ((a) != (a2[i])): 'string' and 'immutable(char)'|
 ||=== Build finished: 1 errors, 0 warnings ===|

 And Code::Blocks jumps me to object.di:

 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
 {
     if (a1.length != a2.length)
  return false;
     foreach(i, a; a1)
     { if (a != a2[i]) // <-- line 487. Uh oh, trying to compare strings
 and chars
     return false;
     }
     return true;
 }

 I had to modify it:

 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
  if (is(typeof(T1.init != T2.init))) // Are T1 and T2 comparable? If not,
 do not bother to compile
 {
    if (a1.length != a2.length) return false;
     foreach(i, a; a1)
     { if (a != a2[i])
         return false;
     }
     return true;
 }

 Another possibility would have it return false, but in that case, array
 comparisons always compile and we lose the ability to use them as test for
 instantiating a template.

 I guess _ArrayEq is some internal called by the constraint, while doing the
 comparison. Saving object.di and recompiling everything allows the templates
 constraints to function and gives me a call to the first find.

 Without the '&& false', it still calls the first find... because it still
 cannot instantiate the second template:

 The first find can be instantiated with T = immutable(char)[] and E =
 immutable(char)[], there is nothing stopping it: T and E are the same type,
 so they are trivially comparable. "two" is a valid target value for ["one",
 "two"].
 The second find would have T1 = immutable(char)[] and T2 = immutable(char)
 and those do not compare.


 testing it, find("one two three", "two") correctly calls the second version
 and returns "two three".

 list. Anyway, for me, it seems to work, if I understand correctly what
 you're doing.

to constraint the second template so it never gets called with: assert(find(s, "two") == ["two"]); because this was in the unittest right under the first template, and I assumed it should work only with the first template. On TDPL page 143 it states that there is no ambiguity between the two templates, so this entire following code should work (could you please try this out with your new object.di if you have any time?). I hope Andrei won't mind for pasting this here: import std.stdio; void main() { } T[] find(T, E)(T[] haystack, E needle) if (is(typeof(haystack[0] != needle) == bool)) { while (haystack.length > 0 && haystack[0] != needle) { haystack = haystack[1 .. $]; } return haystack; } unittest { double[] d = [1.5, 2.4]; assert(find(d, 1.0) == null); assert(find(d, 1.5) == d); string[] s = ["one", "two"]; assert(find(s, "two") == ["two"]); } T1[] find(T1, T2)(T1[] longer, T2[] shorter) if (is(typeof(longer[0 .. 1] == shorter) : bool)) { while (longer.length >= shorter.length) { if (longer[0 .. shorter.length] == shorter) break; longer = longer[1 .. $]; } return longer; } unittest { double[] d1 = [6.0, 1.5, 2.4, 3]; float[] d2 = [1.5, 2.4]; assert(find(d1, d2) == d1[1 .. $]); }
 Btw, if you find yourself using the same constraint regularly, you can
 abstract it away in another template that returns (er, becomes, rather) a
 boolean:

 template areComparable(T1, T2)
 {
    enum bool areComparable = is(typeof(T1.init == T2.init)); // eponymous
 template trick
 }

 And then:

 T[] find(T, E)(T[] haystack, E needle)
     if (areComparable!(T, E))
 {
 }


 T[] find(T, E)(T[] longer, E[] shorter)
     if (areComparable!(T, E))

 {
 }

 Which makes for cleaner code. I renamed T1 and T2 to T and E, so showcase
 the difference between the two.


 Philippe

with some helper functions. That's a pretty cool trick, thanks! --0016364d22e54f8a85048ca2cbf9 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Sat, Jul 31, 2010 at 12:04 AM, Philip= pe Sigaud <span dir=3D"ltr">&lt;<a href=3D"mailto:philippe.sigaud gmail.com= ">philippe.sigaud gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"g= mail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(= 204, 204, 204); padding-left: 1ex;"> <div>First, =A0trying a copy-paste of your code gives me an error in object= .di</div><div>(DMD 2.047 on Windows)</div><div><br></div></blockquote><div>= <br>Yes, I get the same error.<br>=A0</div><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>C:\dmd\windows\bin\..\..\src\druntime\import\object.di|487|= Error: incompatible types for ((a) !=3D (a2[i])): &#39;string&#39; and &#39= ;immutable(char)&#39;|</div> <div>||=3D=3D=3D Build finished: 1 errors, 0 warnings =3D=3D=3D|</div><div>= <br></div><div>And Code::Blocks jumps me to object.di:</div><div><br></div>= <div>bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)</div><div>{</div><div>=A0=A0 = =A0if (a1.length !=3D a2.length)</div> <div><span style=3D"white-space: pre-wrap;"> </span>return false;</div><div=
=A0=A0 =A0foreach(i, a; a1)</div><div>=A0=A0 =A0{<span style=3D"white-spac=

o compare strings and chars</div> <div><span style=3D"white-space: pre-wrap;"> </span> =A0 =A0return false;</= div><div>=A0=A0 =A0}</div><div>=A0=A0 =A0return true;</div><div>}</div><div=
<br></div><div>I had to modify it:</div><div><br></div><div>bool _ArrayEq(=

<div><span style=3D"white-space: pre-wrap;"> </span>if (is(typeof(T1.init != =3D T2.init))) // Are T1 and T2 comparable? If not, do not bother to compil= e</div><div>{</div><div>=A0=A0 if (a1.length !=3D a2.length) return false;<= /div> <div>=A0=A0 =A0foreach(i, a; a1)</div><div>=A0=A0 =A0{<span style=3D"white-= space: pre-wrap;"> </span>if (a !=3D a2[i])</div><div>=A0=A0 =A0 =A0 =A0ret= urn false;</div><div>=A0=A0 =A0}</div><div>=A0=A0 =A0return true;</div><div=
}</div><div><br></div>

y comparisons always compile and we lose the ability to use them as test fo= r instantiating a template.</div><div><br></div><div>I guess _ArrayEq is so= me internal called by the constraint, while doing the comparison. Saving ob= ject.di and recompiling everything allows the templates constraints to func= tion and gives me a call to the first find.</div> <div><br></div><div>Without the &#39;&amp;&amp; false&#39;, it still calls = the first find... because it still cannot instantiate the second template:<= /div><div><br></div><div>The first find can be instantiated with T =3D immu= table(char)[] and E =3D immutable(char)[], there is nothing stopping it: T = and E are the same type, so they are trivially comparable. &quot;two&quot; = is a valid target value for [&quot;one&quot;, &quot;two&quot;].</div> <div>The second find would have T1 =3D immutable(char)[] and T2 =3D immutab= le(char) and those do not compare.</div><div><br></div><div><br></div><div>= testing it, find(&quot;one two three&quot;, &quot;two&quot;) correctly call= s the second version and returns &quot;two three&quot;.</div> <div><br>=A0</div></blockquote><blockquote class=3D"gmail_quote" style=3D"m= argin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); paddin= g-left: 1ex;"><div></div><div>So, maybe you just found a bug in object.di._= ArrayEq. I&#39;ll post on the main list. Anyway, for me, it seems to work, = if I understand correctly what you&#39;re doing.</div> <div><br></div></blockquote><div><br>What I am trying to do is to get the c= ode sample from TDPL working. I tried to constraint the second template so = it never gets called with:<br><br>=A0=A0=A0 assert(find(s, &quot;two&quot;)= =3D=3D [&quot;two&quot;]);<br> <br>because this was in the unittest right under the first template, and I = assumed it should work only with the first template. On TDPL page 143 it st= ates that there is no ambiguity between the two templates, so this entire f= ollowing code should work (could you please try this out with your new obje= ct.di if you have any time?). I hope Andrei won&#39;t mind for pasting this= here:<br> <br><br>import std.stdio;<br><br>void main()<br>{<br>}<br><br>T[] find(T, E= )(T[] haystack, E needle)<br>=A0=A0=A0 if (is(typeof(haystack[0] !=3D needl= e) =3D=3D bool))<br>{<br>=A0=A0=A0 while (haystack.length &gt; 0 &amp;&amp;= haystack[0] !=3D needle) {<br> =A0=A0=A0=A0=A0=A0=A0 haystack =3D haystack[1 .. $];<br>=A0=A0=A0 }<br>=A0= =A0=A0 return haystack;<br>}<br><br>unittest {<br>=A0=A0=A0 double[] d =3D = [1.5, 2.4];<br>=A0=A0=A0 assert(find(d, 1.0) =3D=3D null);<br>=A0=A0=A0 ass= ert(find(d, 1.5) =3D=3D d);<br>=A0=A0=A0 string[] s =3D [&quot;one&quot;, &= quot;two&quot;];<br> =A0=A0=A0 assert(find(s, &quot;two&quot;) =3D=3D [&quot;two&quot;]);<br>}<b= r><br><br>T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br>=A0=A0=A0 if (is(= typeof(longer[0 .. 1] =3D=3D shorter) : bool))<br>{<br>=A0=A0=A0 while (lon= ger.length &gt;=3D shorter.length) {<br> =A0=A0=A0=A0=A0=A0=A0 if (longer[0 .. shorter.length] =3D=3D shorter)<br>= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 longer = =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br>}<br><br>= unittest {<br>=A0=A0=A0 double[] d1 =3D [6.0, 1.5, 2.4, 3];<br>=A0=A0=A0 fl= oat[] d2 =3D [1.5, 2.4];<br> =A0=A0=A0 assert(find(d1, d2) =3D=3D d1[1 .. $]);<br>}<br><br>=A0</div><blo= ckquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border-le= ft: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div></div><div>Btw, = if you find yourself using the same constraint regularly, you can abstract = it away in another template that returns (er, becomes, rather) a boolean:</= div> <div><br></div><div>template areComparable(T1, T2)</div><div>{</div><div>= =A0=A0 enum bool areComparable =3D is(typeof(T1.init =3D=3D T2.init)); // e= ponymous template trick</div><div>}</div><div><br></div><div>And then:</div=
<div><br>

</div><div><span style=3D"font-family: arial,sans-serif; font-size: 12.5px;= border-collapse: collapse;"><div style=3D"color: rgb(80, 0, 80);"><div cla= ss=3D"im">T[] find(T, E)(T[] haystack, E needle)<br></div>=A0=A0=A0 if (are= Comparable!(T, E))<br> </div><div style=3D"color: rgb(80, 0, 80);">{<br>}<br><br><br></div><div st= yle=3D"color: rgb(80, 0, 80);">T[] find(T, E)(T[] longer, E[] shorter)<br><= /div>=A0=A0=A0 if (areComparable!(T, E))<div style=3D"color: rgb(80, 0, 80)= ;"> <br>{<br>}<br></div><div style=3D"color: rgb(80, 0, 80);"><br></div><div st= yle=3D"color: rgb(80, 0, 80);">Which makes for cleaner code. I renamed T1 a= nd T2 to T and E, so showcase the difference between the two.</div> <div style=3D"color: rgb(80, 0, 80);"><br></div><div style=3D"color: rgb(80= , 0, 80);"><br></div><div style=3D"color: rgb(80, 0, 80);"><span style=3D"f= ont-size: 12.5px;">Philippe</span></div> <div style=3D"color: rgb(80, 0, 80);"><br></div></span></div></blockquote><= div>=A0</div></div>I was actually thinking about ways of simplifying the co= nstraint definitions with some helper functions. That&#39;s a pretty cool t= rick, thanks!<br> --0016364d22e54f8a85048ca2cbf9--
Jul 30 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--00221540056e5fa160048cb08f22
Content-Type: text/plain; charset=ISO-8859-1

I think there really is some bug here. I tried to use your template helper
function, and it seems the order in which I put two constraints in a
template signature changes the way dmd compiles the code. Consider this:

import std.stdio;

void main()
{
}

template areComparable(T1, T2)
{
   enum bool areComparable = is(typeof(T1.init == T2.init)); // eponymous
template trick
}

T[] find(T, E)(T[] haystack, E needle)
    if (is(typeof(haystack[0] != needle) == bool) &&
    areComparable!(T, E))
{
    while (haystack.length > 0 && haystack[0] != needle) {
        haystack = haystack[1 .. $];
    }
    return haystack;
}

T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (is(typeof(longer[0 .. 1] == shorter) : bool) && (areComparable!(T1,
T2)))

{
    while (longer.length >= shorter.length) {
        if (longer[0 .. shorter.length] == shorter)
            break;
        longer = longer[1 .. $];
    }
    return longer;
}

unittest {
    double[] d = [1.5, 2.4];
    assert(find(d, 1.0) == null);
    assert(find(d, 1.5) == d);
    string[] s = ["one", "two"];
    assert(find(s, "two") == ["two"]);
}

This will give out the error "incompatible types for comparing of string and
immutable(char)". But if I reverse the order of the constraints in the
second template, like so:

import std.stdio;

void main()
{
}

template areComparable(T1, T2)
{
   enum bool areComparable = is(typeof(T1.init == T2.init)); // eponymous
template trick
}

T[] find(T, E)(T[] haystack, E needle)
    if (is(typeof(haystack[0] != needle) == bool) &&
    areComparable!(T, E))
{
    while (haystack.length > 0 && haystack[0] != needle) {
        haystack = haystack[1 .. $];
    }
    return haystack;
}


T1[] find(T1, T2)(T1[] longer, T2[] shorter)
    if (areComparable!(T1, T2) && is(typeof(longer[0 .. 1] == shorter) :
bool))
{
    while (longer.length >= shorter.length) {
        if (longer[0 .. shorter.length] == shorter)
            break;
        longer = longer[1 .. $];
    }
    return longer;
}

unittest {
    double[] d = [1.5, 2.4];
    assert(find(d, 1.0) == null);
    assert(find(d, 1.5) == d);
    string[] s = ["one", "two"];
    assert(find(s, "two") == ["two"]);
}

Then this happily compiles. All of the asserts will call the first templated
function.


On Sat, Jul 31, 2010 at 12:04 AM, Philippe Sigaud <philippe.sigaud gmail.com
 wrote:

 First,  trying a copy-paste of your code gives me an error in object.di
 (DMD 2.047 on Windows)

 C:\dmd\windows\bin\..\..\src\druntime\import\object.di|487|Error:
 incompatible types for ((a) != (a2[i])): 'string' and 'immutable(char)'|
 ||=== Build finished: 1 errors, 0 warnings ===|

 And Code::Blocks jumps me to object.di:

 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
 {
     if (a1.length != a2.length)
  return false;
     foreach(i, a; a1)
     { if (a != a2[i]) // <-- line 487. Uh oh, trying to compare strings
 and chars
     return false;
     }
     return true;
 }

 I had to modify it:

 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
  if (is(typeof(T1.init != T2.init))) // Are T1 and T2 comparable? If not,
 do not bother to compile
 {
    if (a1.length != a2.length) return false;
     foreach(i, a; a1)
     { if (a != a2[i])
         return false;
     }
     return true;
 }

 Another possibility would have it return false, but in that case, array
 comparisons always compile and we lose the ability to use them as test for
 instantiating a template.

 I guess _ArrayEq is some internal called by the constraint, while doing the
 comparison. Saving object.di and recompiling everything allows the templates
 constraints to function and gives me a call to the first find.

 Without the '&& false', it still calls the first find... because it still
 cannot instantiate the second template:

 The first find can be instantiated with T = immutable(char)[] and E =
 immutable(char)[], there is nothing stopping it: T and E are the same type,
 so they are trivially comparable. "two" is a valid target value for ["one",
 "two"].
 The second find would have T1 = immutable(char)[] and T2 = immutable(char)
 and those do not compare.


 testing it, find("one two three", "two") correctly calls the second version
 and returns "two three".

 So, maybe you just found a bug in object.di._ArrayEq. I'll post on the main
 list. Anyway, for me, it seems to work, if I understand correctly what
 you're doing.

 Btw, if you find yourself using the same constraint regularly, you can
 abstract it away in another template that returns (er, becomes, rather) a
 boolean:

 template areComparable(T1, T2)
 {
    enum bool areComparable = is(typeof(T1.init == T2.init)); // eponymous
 template trick
 }

 And then:

 T[] find(T, E)(T[] haystack, E needle)
     if (areComparable!(T, E))
 {
 }


 T[] find(T, E)(T[] longer, E[] shorter)
     if (areComparable!(T, E))

 {
 }

 Which makes for cleaner code. I renamed T1 and T2 to T and E, so showcase
 the difference between the two.


 Philippe

--00221540056e5fa160048cb08f22 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable I think there really is some bug here. I tried to use your template helper = function, and it seems the order in which I put two constraints in a templa= te signature changes the way dmd compiles the code. Consider this:<br><br> import std.stdio;<br><br>void main()<br>{<br>}<br><br>template areComparabl= e(T1, T2)<br>{<br>=A0=A0 enum bool areComparable =3D is(typeof(T1.init =3D= =3D T2.init)); // eponymous template trick<br>}<br><br>T[] find(T, E)(T[] h= aystack, E needle)<br> =A0=A0=A0 if (is(typeof(haystack[0] !=3D needle) =3D=3D bool) &amp;&amp;<br=
=A0=A0=A0 areComparable!(T, E))<br>{<br>=A0=A0=A0 while (haystack.length &=

ck =3D haystack[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return haystack;<br> }<br><br>T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br>=A0=A0=A0 if (is(t= ypeof(longer[0 .. 1] =3D=3D shorter) : bool) &amp;&amp; (areComparable!(T1,= T2)))<br>=A0=A0=A0 <br>{<br>=A0=A0=A0 while (longer.length &gt;=3D shorter= .length) {<br>=A0=A0=A0=A0=A0=A0=A0 if (longer[0 .. shorter.length] =3D=3D = shorter)<br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 longer = =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br>}<br><br>= unittest {<br>=A0=A0=A0 double[] d =3D [1.5, 2.4];<br>=A0=A0=A0 assert(find= (d, 1.0) =3D=3D null);<br>=A0=A0=A0 assert(find(d, 1.5) =3D=3D d);<br>=A0= =A0=A0 string[] s =3D [&quot;one&quot;, &quot;two&quot;];<br> =A0=A0=A0 assert(find(s, &quot;two&quot;) =3D=3D [&quot;two&quot;]);<br>}<b= r><br>This will give out the error &quot;incompatible types for comparing o= f string and immutable(char)&quot;. But if I reverse the order of the const= raints in the second template, like so:<br> <br>import std.stdio;<br><br>void main()<br>{<br>}<br><br>template areCompa= rable(T1, T2)<br>{<br>=A0=A0 enum bool areComparable =3D is(typeof(T1.init = =3D=3D T2.init)); // eponymous template trick<br>}<br><br>T[] find(T, E)(T[= ] haystack, E needle)<br> =A0=A0=A0 if (is(typeof(haystack[0] !=3D needle) =3D=3D bool) &amp;&amp;<br=
=A0=A0=A0 areComparable!(T, E))<br>{<br>=A0=A0=A0 while (haystack.length &=

ck =3D haystack[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return haystack;<br> }<br><br><br>T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br>=A0=A0=A0 if (= areComparable!(T1, T2) &amp;&amp; is(typeof(longer[0 .. 1] =3D=3D shorter) = : bool))<br>{<br>=A0=A0=A0 while (longer.length &gt;=3D shorter.length) {<b= r>=A0=A0=A0=A0=A0=A0=A0 if (longer[0 .. shorter.length] =3D=3D shorter)<br> =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 longer = =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br>}<br><br>= unittest {<br>=A0=A0=A0 double[] d =3D [1.5, 2.4];<br>=A0=A0=A0 assert(find= (d, 1.0) =3D=3D null);<br>=A0=A0=A0 assert(find(d, 1.5) =3D=3D d);<br>=A0= =A0=A0 string[] s =3D [&quot;one&quot;, &quot;two&quot;];<br> =A0=A0=A0 assert(find(s, &quot;two&quot;) =3D=3D [&quot;two&quot;]);<br>}<b= r><br>Then this happily compiles. All of the asserts will call the first te= mplated function.<br><br><br><div class=3D"gmail_quote">On Sat, Jul 31, 201= 0 at 12:04 AM, Philippe Sigaud <span dir=3D"ltr">&lt;<a href=3D"mailto:phil= ippe.sigaud gmail.com">philippe.sigaud gmail.com</a>&gt;</span> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"><div>First, =A0tr= ying a copy-paste of your code gives me an error in object.di</div><div>(DM= D 2.047 on Windows)</div> <div><br></div><div>C:\dmd\windows\bin\..\..\src\druntime\import\object.di|= 487|Error: incompatible types for ((a) !=3D (a2[i])): &#39;string&#39; and = &#39;immutable(char)&#39;|</div> <div>||=3D=3D=3D Build finished: 1 errors, 0 warnings =3D=3D=3D|</div><div>= <br></div><div>And Code::Blocks jumps me to object.di:</div><div><br></div>= <div>bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)</div><div>{</div><div>=A0=A0 = =A0if (a1.length !=3D a2.length)</div> <div><span style=3D"white-space: pre-wrap;"> </span>return false;</div><div=
=A0=A0 =A0foreach(i, a; a1)</div><div>=A0=A0 =A0{<span style=3D"white-spac=

o compare strings and chars</div> <div><span style=3D"white-space: pre-wrap;"> </span> =A0 =A0return false;</= div><div>=A0=A0 =A0}</div><div>=A0=A0 =A0return true;</div><div>}</div><div=
<br></div><div>I had to modify it:</div><div><br></div><div>bool _ArrayEq(=

<div><span style=3D"white-space: pre-wrap;"> </span>if (is(typeof(T1.init != =3D T2.init))) // Are T1 and T2 comparable? If not, do not bother to compil= e</div><div>{</div><div>=A0=A0 if (a1.length !=3D a2.length) return false;<= /div> <div>=A0=A0 =A0foreach(i, a; a1)</div><div>=A0=A0 =A0{<span style=3D"white-= space: pre-wrap;"> </span>if (a !=3D a2[i])</div><div>=A0=A0 =A0 =A0 =A0ret= urn false;</div><div>=A0=A0 =A0}</div><div>=A0=A0 =A0return true;</div><div=
}</div><div><br></div>

y comparisons always compile and we lose the ability to use them as test fo= r instantiating a template.</div><div><br></div><div>I guess _ArrayEq is so= me internal called by the constraint, while doing the comparison. Saving ob= ject.di and recompiling everything allows the templates constraints to func= tion and gives me a call to the first find.</div> <div><br></div><div>Without the &#39;&amp;&amp; false&#39;, it still calls = the first find... because it still cannot instantiate the second template:<= /div><div><br></div><div>The first find can be instantiated with T =3D immu= table(char)[] and E =3D immutable(char)[], there is nothing stopping it: T = and E are the same type, so they are trivially comparable. &quot;two&quot; = is a valid target value for [&quot;one&quot;, &quot;two&quot;].</div> <div>The second find would have T1 =3D immutable(char)[] and T2 =3D immutab= le(char) and those do not compare.</div><div><br></div><div><br></div><div>= testing it, find(&quot;one two three&quot;, &quot;two&quot;) correctly call= s the second version and returns &quot;two three&quot;.</div> <div><br></div><div>So, maybe you just found a bug in object.di._ArrayEq. I= &#39;ll post on the main list. Anyway, for me, it seems to work, if I under= stand correctly what you&#39;re doing.</div><div><br></div><div>Btw, if you= find yourself using the same constraint regularly, you can abstract it awa= y in another template that returns (er, becomes, rather) a boolean:</div> <div><br></div><div>template areComparable(T1, T2)</div><div>{</div><div>= =A0=A0 enum bool areComparable =3D is(typeof(T1.init =3D=3D T2.init)); // e= ponymous template trick</div><div>}</div><div><br></div><div>And then:</div=
<div><br>

</div><div><span style=3D"font-family: arial,sans-serif; font-size: 12.5px;= border-collapse: collapse;"><div style=3D"color: rgb(80, 0, 80);"><div cla= ss=3D"im">T[] find(T, E)(T[] haystack, E needle)<br></div>=A0=A0=A0 if (are= Comparable!(T, E))<br> </div><div style=3D"color: rgb(80, 0, 80);">{<br>}<br><br><br></div><div st= yle=3D"color: rgb(80, 0, 80);">T[] find(T, E)(T[] longer, E[] shorter)<br><= /div>=A0=A0=A0 if (areComparable!(T, E))<div style=3D"color: rgb(80, 0, 80)= ;"> <br>{<br>}<br></div><div style=3D"color: rgb(80, 0, 80);"><br></div><div st= yle=3D"color: rgb(80, 0, 80);">Which makes for cleaner code. I renamed T1 a= nd T2 to T and E, so showcase the difference between the two.</div> <div style=3D"color: rgb(80, 0, 80);"><br></div><div style=3D"color: rgb(80= , 0, 80);"><br></div><div style=3D"color: rgb(80, 0, 80);"><span style=3D"f= ont-size: 12.5px;">Philippe</span></div> <div style=3D"color: rgb(80, 0, 80);"><br></div></span></div> </blockquote></div><br> --00221540056e5fa160048cb08f22--
Jul 31 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--00032555a3daf9ea57048cc99365
Content-Type: text/plain; charset=ISO-8859-1

On Sat, Jul 31, 2010 at 17:24, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

 I think there really is some bug here. I tried to use your template helper
 function, and it seems the order in which I put two constraints in a
 template signature changes the way dmd compiles the code. Consider this:

 T[] find(T, E)(T[] haystack, E needle)
     if (is(typeof(haystack[0] != needle) == bool) &&
     areComparable!(T, E))

 ...

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
     if (is(typeof(longer[0 .. 1] == shorter) : bool) && (areComparable!(T1,
 T2)))

 This will give out the error "incompatible types for comparing of string
 and immutable(char)".

That's because the first part of the constraint is tested, to allow for short-circuiting the second part. So the bad array comparison triggers the problem in object._EqArray. You should always test for the most general constraint first, I guess. In this particular case, use areComparable!(A,B) as the first argument to && in both templates.
 But if I reverse the order of the constraints in the second template, like
 so:

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
     if (areComparable!(T1, T2) && is(typeof(longer[0 .. 1] == shorter) :
 bool))

 Then this happily compiles.

Well, yes. The second template cannot be instantiated: T1 is a string, T2 is a character. So isComparable evaluates to 'false' and the constraints short-circuits to 'false'.
 All of the asserts will call the first templated function.

cases. That's what the first version of find() do. If you test: assert(find(d, [1.5]); // [1.5] is a one-element array. assert(find(d, [1.5, 2.4]); // finding d in d. assert(find("one two three", "two"); it will activate the second version for all these new asserts: you are looking for a sequence of elements in a sequence of elements, which is what the second find does. Philippe --00032555a3daf9ea57048cc99365 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Sat, Jul 31, 2010 at 17:24, Andrej Mi= trovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">= andrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gm= ail_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-le= ft:1ex;"> I think there really is some bug here. I tried to use your template helper = function, and it seems the order in which I put two constraints in a templa= te signature changes the way dmd compiles the code. Consider this:<div clas= s=3D"im"> </div></blockquote><div>=A0</div><blockquote class=3D"gmail_quote" style=3D= "margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class= =3D"im">T[] find(T, E)(T[] haystack, E needle)</div> =A0=A0=A0 if (is(typeof(haystack[0] !=3D needle) =3D=3D bool) &amp;&amp;<br=
=A0=A0=A0 areComparable!(T, E))<div class=3D"im"><br></div></blockquote><d=

:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"> <div class=3D"im">T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br></div>=A0= =A0=A0 if (is(typeof(longer[0 .. 1] =3D=3D shorter) : bool) &amp;&amp; (are= Comparable!(T1, T2)))<div class=3D"im"></div></blockquote><div><br></div><d= iv>=A0</div> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex;"><div class=3D"im">This will give out the er= ror &quot;incompatible types for comparing of string and immutable(char)&qu= ot;. </div> </blockquote><div><br></div><div>That&#39;s because the first part of the c= onstraint is tested, to allow for short-circuiting the second part. So the = bad array comparison triggers the problem in object._EqArray.</div><div> <br></div><div>You should always test for the most general constraint first= , I guess. In this particular case, use areComparable!(A,B) as the first ar= gument to &amp;&amp; in both templates.</div><div><br></div><div>=A0</div> <blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-left:1p= x #ccc solid;padding-left:1ex;"><div class=3D"im">But if I reverse the orde= r of the constraints in the second template, like so:</div><div class=3D"im= "><br> T1[] find(T1, T2)(T1[] longer, T2[] shorter)</div>=A0=A0=A0 if (areComparab= le!(T1, T2) &amp;&amp; is(typeof(longer[0 .. 1] =3D=3D shorter) : bool))<di= v class=3D"im"></div></blockquote><div>=A0</div><blockquote class=3D"gmail_= quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1= ex;"> <div class=3D"im">Then this happily compiles. </div></blockquote><div><br><= /div><div>Well, yes. The second template cannot be instantiated: T1 is a st= ring, T2 is a character. So isComparable evaluates to &#39;false&#39; and t= he constraints short-circuits to &#39;false&#39;.</div> <div>=A0</div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;= border-left:1px #ccc solid;padding-left:1ex;"><div class=3D"im">All of the = asserts will call the first templated function.</div><div><div></div><div c= lass=3D"h5"> <br></div></div></blockquote><div><br></div><div>Because you are looking fo= r an element in a sequence of element in all three cases. That&#39;s what t= he first version of find() do.</div><div>If you test:</div><div><br></div> <div>assert(find(d, [1.5]); // [1.5] is a one-element array.</div><div>asse= rt(find(d, [1.5, 2.4]); // finding d in d.</div><div>assert(find(&quot;one = two three&quot;, &quot;two&quot;);</div><div><br></div><div><br></div><div> it will activate the second version for all these new asserts: you are look= ing for a sequence of elements in a sequence of elements, which is what the= second find does.</div><div><br></div><div>Philippe</div><div><br></div> <div><br></div><div>=A0</div></div> --00032555a3daf9ea57048cc99365--
Aug 01 2010
prev sibling next sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--001636c5b4f38c9cbd048cc9d200
Content-Type: text/plain; charset=ISO-8859-1

On Sat, Jul 31, 2010 at 00:58, Andrej Mitrovic
<andrej.mitrovich gmail.com>wrote:

 could you please try this out with your new object.di if you have any
 time?). I hope Andrei won't mind for pasting this here:


 (snip)

 unittest {
     double[] d1 = [6.0, 1.5, 2.4, 3];
     float[] d2 = [1.5, 2.4];
     assert(find(d1, d2) == d1[1 .. $]); // unit test failure on line 40.
 }

The assert fails, because find(d1, d2) does not returns [1.5, 2.4, 3] in my case. That's because floating points types are notoriously difficult to test for equality: double d = 2.4; float f = 2.4; writeln(d == f); // false! 2.4 do not have the same representation as a float or as a double. So I guess there must have been some pb with the testing Andrei has done on the examples, because this particular example do not work. To test floating point values, use std.math.approxEqual. For a function like find() you can imagine either using approxEqual as the comparator when you detect T/E, T1/T2 to be floating point values, or defer to the user to give you a valid comparator, as an alias: import std.functional: binaryFun; // template transforming strings like "a ==b" into functions. T1[] find(alias comparator = "a == b", T1, T2)(T1[] longer, T2[] shorter) if (is(typeof( binaryFun!comparator(longer[0 .. 1], shorter)) : bool)) { while (longer.length >= shorter.length) { if (binaryFun!comparator(longer[0 .. shorter.length], shorter)) break; longer = longer[1 .. $]; } return longer; } usage: void main() { double[] d = [1.0, 1.5, 2.4, 3.14]; float[] f = [1.5, 2.4]; writeln(find(d, f)); // use a == b as a comparator, so returns 3.14, did not see 1.5 float and 1.5 double as equal writeln(find!approxEqual(d, f)); // [1.5, 2.4, 3.14] } btw, the behavior is not correct: find(d,f) should return an empty array, not [3.14]... I was actually thinking about ways of simplifying the constraint definitions
 with some helper functions. That's a pretty cool trick, thanks!

It's used throughout Phobos, particularly in the template-heavy modules, like std.algorithm or std.range. Philippe --001636c5b4f38c9cbd048cc9d200 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <div class=3D"gmail_quote">On Sat, Jul 31, 2010 at 00:58, Andrej Mitrovic <= span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">andrej.m= itrovich gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gmail_quot= e" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"=

ime?). I hope Andrei won&#39;t mind for pasting this here:<br><div class=3D= "gmail_quote"><div><div class=3D"im"><br><br></div></div></div></blockquote=

argin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div class= =3D"gmail_quote"><div><div class=3D"im"></div><div class=3D"im">unittest {<= br></div><div class=3D"im"> =A0=A0=A0 double[] d1 =3D [6.0, 1.5, 2.4, 3];<br>=A0=A0=A0 float[] d2 =3D [= 1.5, 2.4];<br> =A0=A0=A0 assert(find(d1, d2) =3D=3D d1[1 .. $]); // unit test failure on l= ine 40.<br>}<br></div></div></div></blockquote><div><br></div><div>The asse= rt fails, because find(d1, d2) does not returns [1.5, 2.4, 3] in my case.</= div><div> That&#39;s because floating points types are notoriously difficult to test = for equality:</div><div><br></div><div>double d =3D 2.4;</div><div>float f = =3D 2.4;</div><div>writeln(d =3D=3D f); // false! 2.4 do not have the same = representation as a float or as a double.</div> <div><br></div><div>So I guess there must have been some pb with the testin= g Andrei has done on the examples, because this particular example do not w= ork.</div><div><br></div><div>To test floating point values, use std.math.a= pproxEqual.</div> <div><br></div><div>For a function like find() you can imagine either using= approxEqual as the comparator=A0when you detect T/E, T1/T2 to be floating = point values, or defer to the user to give you a valid comparator, as an al= ias:</div> <div><br></div><div>import std.functional: binaryFun; // template transform= ing strings like &quot;a =3D=3Db&quot; into functions.</div><div><br></div>= <div><span class=3D"Apple-style-span" style=3D"font-family: arial, sans-ser= if; font-size: 12.5px; border-collapse: collapse; "><div class=3D"im" style= =3D"color: rgb(80, 0, 80); "> T1[] find(alias comparator =3D &quot;a =3D=3D b&quot;, T1, T2)(T1[] longer,= T2[] shorter)<br></div>=A0=A0=A0 if (is(typeof(</span></div><div><span cla= ss=3D"Apple-style-span" style=3D"font-family: arial, sans-serif; font-size:= 12.5px; border-collapse: collapse; ">=A0=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 = =A0 =A0 =A0 binaryFun!comparator(longer[0 .. 1], shorter)) : bool))<div cla= ss=3D"im" style=3D"color: rgb(80, 0, 80); "> <br>{<br>=A0=A0=A0 while (longer.length &gt;=3D shorter.length) {<br>=A0=A0= =A0=A0=A0=A0=A0 if (binaryFun!comparator(longer[0 .. shorter.length], short= er))<br>=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 break;<br>=A0=A0=A0=A0=A0=A0=A0 l= onger =3D longer[1 .. $];<br>=A0=A0=A0 }<br>=A0=A0=A0 return longer;<br> }<br></div></span></div><div><br></div><div><br></div><div>usage:</div><div=
<div><br></div><div>void main()</div><div>{</div><div>=A0=A0 =A0double[] d=

div><div>=A0=A0 =A0writeln(find(d, f)); // use a =3D=3D b as a comparator, = so returns 3.14, did not see 1.5 float and 1.5 double as equal</div> <div>=A0=A0 =A0writeln(find!approxEqual(d, f)); // [1.5, 2.4, 3.14]</div><d= iv>}</div></div><div><br></div><div>btw, the behavior is not correct: find(= d,f) should return an empty array, not [3.14]...</div><div><br></div><div><= br> </div><blockquote class=3D"gmail_quote" style=3D"margin:0 0 0 .8ex;border-l= eft:1px #ccc solid;padding-left:1ex;"><div class=3D"gmail_quote"><div><div = class=3D"im">I was actually thinking about ways of simplifying the constrai= nt definitions with some helper functions. That&#39;s a pretty cool trick, = thanks!</div> </div></div> </blockquote></div><br><div>It&#39;s used throughout Phobos, particularly i= n the template-heavy modules, like std.algorithm or std.range.</div><div><b= r></div><div>Philippe</div> --001636c5b4f38c9cbd048cc9d200--
Aug 01 2010
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
--0016e6d5096c03761b048ccabb18
Content-Type: text/plain; charset=ISO-8859-1

On Sun, Aug 1, 2010 at 11:15 PM, Philippe Sigaud
<philippe.sigaud gmail.com>wrote:

 On Sat, Jul 31, 2010 at 17:24, Andrej Mitrovic <andrej.mitrovich gmail.com
 wrote:

 I think there really is some bug here. I tried to use your template helper
 function, and it seems the order in which I put two constraints in a
 template signature changes the way dmd compiles the code. Consider this:

 T[] find(T, E)(T[] haystack, E needle)
     if (is(typeof(haystack[0] != needle) == bool) &&
     areComparable!(T, E))

 ...

 T1[] find(T1, T2)(T1[] longer, T2[] shorter)
     if (is(typeof(longer[0 .. 1] == shorter) : bool) &&
 (areComparable!(T1, T2)))

 This will give out the error "incompatible types for comparing of string
 and immutable(char)".

That's because the first part of the constraint is tested, to allow for short-circuiting the second part. So the bad array comparison triggers the problem in object._EqArray. You should always test for the most general constraint first, I guess. In this particular case, use areComparable!(A,B) as the first argument to && in both templates.

false && true will short circuit to false (this is normal). true && false will short circuit to true? How can that be? It's not a logical OR, its an AND, and as far as I know both expressions need to be True to evaluate to True. Or is it different for template constraints? Thanks again for the std.math.approxEqual and binaryFun tips. --0016e6d5096c03761b048ccabb18 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Sun, Aug 1, 2010 at 11:15 PM, Philipp= e Sigaud <span dir=3D"ltr">&lt;<a href=3D"mailto:philippe.sigaud gmail.com"=
philippe.sigaud gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gm=

04, 204, 204); padding-left: 1ex;"> <br><br><div class=3D"gmail_quote"><div class=3D"im">On Sat, Jul 31, 2010 a= t 17:24, Andrej Mitrovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mit= rovich gmail.com" target=3D"_blank">andrej.mitrovich gmail.com</a>&gt;</spa= n> wrote:<br> <blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; borde= r-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;"> I think there really is some bug here. I tried to use your template helper = function, and it seems the order in which I put two constraints in a templa= te signature changes the way dmd compiles the code. Consider this:<div> </div></blockquote><div>=A0</div></div><blockquote class=3D"gmail_quote" st= yle=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204)= ; padding-left: 1ex;"><div>T[] find(T, E)(T[] haystack, E needle)</div><div= class=3D"im"> =A0=A0=A0 if (is(typeof(haystack[0] !=3D needle) =3D=3D bool) &amp;&amp;<br=
=A0=A0=A0 areComparable!(T, E))<div><br></div></div></blockquote><div>...<=

e=3D"margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); = padding-left: 1ex;"> <div>T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br></div>=A0=A0=A0 if (is= (typeof(longer[0 .. 1] =3D=3D shorter) : bool) &amp;&amp; (areComparable!(T= 1, T2)))<div></div></blockquote><div><br></div><div>=A0</div> </div><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>This w= ill give out the error &quot;incompatible types for comparing of string and= immutable(char)&quot;. </div> </blockquote><div><br></div><div>That&#39;s because the first part of the c= onstraint is tested, to allow for short-circuiting the second part. So the = bad array comparison triggers the problem in object._EqArray.</div><div> <br></div><div>You should always test for the most general constraint first= , I guess. In this particular case, use areComparable!(A,B) as the first ar= gument to &amp;&amp; in both templates.</div><br></div></blockquote><div> =A0</div></div>Let me see if I&#39;m getting this right. <br><br>false &amp= ;&amp; true will short circuit to false (this is normal).<br><br>true &amp;= &amp; false will short circuit to true? How can that be? It&#39;s not a log= ical OR, its an AND, and as far as I know both expressions need to be True = to evaluate to True. Or is it different for template constraints?<br> <br>Thanks again for the std.math.approxEqual and binaryFun tips.<br> --0016e6d5096c03761b048ccabb18--
Aug 01 2010
prev sibling parent Philippe Sigaud <philippe.sigaud gmail.com> writes:
--00151747c070f61793048cd10887
Content-Type: text/plain; charset=ISO-8859-1

On Mon, Aug 2, 2010 at 00:37, Andrej Mitrovic <andrej.mitrovich gmail.com>wrote:

 That's because the first part of the constraint is tested, to allow for
 short-circuiting the second part. So the bad array comparison triggers the
 problem in object._EqArray.

 You should always test for the most general constraint first, I guess. In
 this particular case, use areComparable!(A,B) as the first argument to && in
 both templates.

false && true will short circuit to false (this is normal). true && false will short circuit to true? How can that be? It's not a logical OR, its an AND, and as far as I know both expressions need to be True to evaluate to True. Or is it different for template constraints?

I was answering you about the "incompatible types" error. The first part of the template, 'is(typeof(longer[0 .. 1] == shorter) : bool', triggers the error and that stops the compilation process. I agree that, if longer[0..1] == shorter is an error, then we could have is(typeof()) result in 'true'. But here what happens is that everything stops. I'll post about this on the main list, see if it's normal behavior or not and add a bug report. Philippe --00151747c070f61793048cd10887 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable <br><br><div class=3D"gmail_quote">On Mon, Aug 2, 2010 at 00:37, Andrej Mit= rovic <span dir=3D"ltr">&lt;<a href=3D"mailto:andrej.mitrovich gmail.com">a= ndrej.mitrovich gmail.com</a>&gt;</span> wrote:<br><blockquote class=3D"gma= il_quote" style=3D"margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-lef= t:1ex;"> <div class=3D"im"><br><div class=3D"gmail_quote"><blockquote class=3D"gmail= _quote" style=3D"margin:0pt 0pt 0pt 0.8ex;border-left:1px solid rgb(204, 20= 4, 204);padding-left:1ex"><div class=3D"gmail_quote"><div>That&#39;s becaus= e the first part of the constraint is tested, to allow for short-circuiting= the second part. So the bad array comparison triggers the problem in objec= t._EqArray.</div> <div> <br></div><div>You should always test for the most general constraint first= , I guess. In this particular case, use areComparable!(A,B) as the first ar= gument to &amp;&amp; in both templates.</div><br></div></blockquote><div> =A0</div></div></div>Let me see if I&#39;m getting this right. <br><br>fals= e &amp;&amp; true will short circuit to false (this is normal).<br><br>true= &amp;&amp; false will short circuit to true? How can that be? It&#39;s not= a logical OR, its an AND, and as far as I know both expressions need to be= True to evaluate to True. Or is it different for template constraints?<br> </blockquote><div><br></div><div>I was answering you about the &quot;incomp= atible types&quot; error. The first part of the template, &#39;is(typeof(lo= nger[0 .. 1] =3D=3D shorter) : bool&#39;, triggers the error and that stops= the compilation process. I agree that, if longer[0..1] =3D=3D shorter is a= n error, then we could have is(typeof()) result in &#39;true&#39;. But here= what happens is that everything stops. I&#39;ll post about this on the mai= n list, see if it&#39;s normal behavior or not and add a bug report.</div> <div><br></div><div><br></div><div>Philippe</div><div><br></div></div> --00151747c070f61793048cd10887--
Aug 01 2010