<br><br><div class="gmail_quote">On Sat, Jul 31, 2010 at 12:04 AM, Philippe Sigaud <span dir="ltr">&lt;<a href="mailto:philippe.sigaud@gmail.com">philippe.sigaud@gmail.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
<div>First,  trying 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> </div><blockquote class="gmail_quote" style="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) != (a2[i])): &#39;string&#39; and &#39;immutable(char)&#39;|</div>
<div>||=== Build finished: 1 errors, 0 warnings ===|</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>    if (a1.length != a2.length)</div>

<div><span style="white-space: pre-wrap;">        </span>return false;</div><div>    foreach(i, a; a1)</div><div>    {<span style="white-space: pre-wrap;">        </span>if (a != a2[i]) // &lt;-- line 487. Uh oh, trying to compare strings and chars</div>

<div><span style="white-space: pre-wrap;">        </span>    return false;</div><div>    }</div><div>    return true;</div><div>}</div><div><br></div><div>I had to modify it:</div><div><br></div><div>bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2) </div>

<div><span style="white-space: pre-wrap;">        </span>if (is(typeof(T1.init != T2.init))) // Are T1 and T2 comparable? If not, do not bother to compile</div><div>{</div><div>   if (a1.length != a2.length) return false;</div>

<div>    foreach(i, a; a1)</div><div>    {<span style="white-space: pre-wrap;">        </span>if (a != a2[i])</div><div>        return false;</div><div>    }</div><div>    return true;</div><div>}</div><div><br></div>
<div>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.</div><div><br></div><div>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.</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 = immutable(char)[] and E = 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 = immutable(char)[] and T2 = immutable(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 calls the second version and returns &quot;two three&quot;.</div>

<div><br> </div></blockquote><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-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 code sample from TDPL working. I tried to constraint the second template so it never gets called with:<br><br>    assert(find(s, &quot;two&quot;) == [&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 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&#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>    if (is(typeof(haystack[0] != needle) == bool))<br>{<br>    while (haystack.length &gt; 0 &amp;&amp; haystack[0] != needle) {<br>
        haystack = haystack[1 .. $];<br>    }<br>    return haystack;<br>}<br><br>unittest {<br>    double[] d = [1.5, 2.4];<br>    assert(find(d, 1.0) == null);<br>    assert(find(d, 1.5) == d);<br>    string[] s = [&quot;one&quot;, &quot;two&quot;];<br>
    assert(find(s, &quot;two&quot;) == [&quot;two&quot;]);<br>}<br><br><br>T1[] find(T1, T2)(T1[] longer, T2[] shorter)<br>    if (is(typeof(longer[0 .. 1] == shorter) : bool))<br>{<br>    while (longer.length &gt;= shorter.length) {<br>
        if (longer[0 .. shorter.length] == shorter)<br>            break;<br>        longer = longer[1 .. $];<br>    }<br>    return longer;<br>}<br><br>unittest {<br>    double[] d1 = [6.0, 1.5, 2.4, 3];<br>    float[] d2 = [1.5, 2.4];<br>
    assert(find(d1, d2) == d1[1 .. $]);<br>}<br><br> </div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 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>   enum bool areComparable = is(typeof(T1.init == T2.init)); // eponymous template trick</div><div>}</div><div><br></div><div>And then:</div><div><br>

</div><div><span style="font-family: arial,sans-serif; font-size: 12.5px; border-collapse: collapse;"><div style="color: rgb(80, 0, 80);"><div class="im">T[] find(T, E)(T[] haystack, E needle)<br></div>    if (areComparable!(T, E))<br>

</div><div style="color: rgb(80, 0, 80);">{<br>}<br><br><br></div><div style="color: rgb(80, 0, 80);">T[] find(T, E)(T[] longer, E[] shorter)<br></div>    if (areComparable!(T, E))<div style="color: rgb(80, 0, 80);">
<br>{<br>}<br></div><div style="color: rgb(80, 0, 80);"><br></div><div style="color: rgb(80, 0, 80);">Which makes for cleaner code. I renamed T1 and T2 to T and E, so showcase the difference between the two.</div>
<div style="color: rgb(80, 0, 80);"><br></div><div style="color: rgb(80, 0, 80);"><br></div><div style="color: rgb(80, 0, 80);"><span style="font-size: 12.5px;">Philippe</span></div>
<div style="color: rgb(80, 0, 80);"><br></div></span></div></blockquote><div> </div></div>I was actually thinking about ways of simplifying the constraint definitions with some helper functions. That&#39;s a pretty cool trick, thanks!<br>