On 9/10/18 1:44 PM, Andrei Alexandrescu wrote:
On 9/10/18 12:46 PM, Steven Schveighoffer wrote:
On 9/10/18 8:58 AM, Steven Schveighoffer wrote:
I'll have to figure out why my specialized range doesn't allow splitting based on " ".

And the answer is: I'm an idiot. Forgot to define empty :) Also my slicing operator accepted ints and not size_t.

I guess a better error message would be in order.


A better error message would help prevent the painful diagnosis that I had to do to actually find the issue.

So the error I got was this:

source/bufref.d(346,36): Error: template std.algorithm.iteration.splitter cannot deduce function from argument types !()(Result, string), candidates are: /Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(3792,6): std.algorithm.iteration.splitter(alias pred = "a == b", Range, Separator)(Range r, Separator s) if (is(typeof(binaryFun!pred(r.front, s)) : bool) && (hasSlicing!Range && hasLength!Range || isNarrowString!Range)) /Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(4163,6): std.algorithm.iteration.splitter(alias pred = "a == b", Range, Separator)(Range r, Separator s) if (is(typeof(binaryFun!pred(r.front, s.front)) : bool) && (hasSlicing!Range || isNarrowString!Range) && isForwardRange!Separator && (hasLength!Separator || isNarrowString!Separator)) /Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(4350,6): std.algorithm.iteration.splitter(alias isTerminator, Range)(Range r) if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(r.front)))) /Users/steves/.dvm/compilers/dmd-2.081.0/osx/bin/../../src/phobos/std/algorithm/iteration.d(4573,6): std.algorithm.iteration.splitter(C)(C[] s) if (isSomeChar!C)

This means I had to look at each line, figure out which overload I'm calling, and then copy all the constraints locally, seeing which ones were true and which ones false.

But it didn't stop there. The problem was hasSlicing!Range. If you look at hasSlicing, it looks like this:

enum bool hasSlicing(R) = isForwardRange!R
    && !isNarrowString!R
    && is(ReturnType!((R r) => r[1 .. 1].length) == size_t)
    && (is(typeof(lvalueOf!R[1 .. 1]) == R) || isInfinite!R)
&& (!is(typeof(lvalueOf!R[0 .. $])) || is(typeof(lvalueOf!R[0 .. $]) == R))
    && (!is(typeof(lvalueOf!R[0 .. $])) || isInfinite!R
        || is(typeof(lvalueOf!R[0 .. $ - 1]) == R))
    && is(typeof((ref R r)
    {
        static assert(isForwardRange!(typeof(r[1 .. 2])));
    }));

Now I had to instrument a whole slew of items. I pasted this whole thing this into my code, added an alias to my range type for R, and then changed the big boolean expression to a bunch of static asserts.

Then I found the true culprit was isForwardRange!R. This led me to requestion my sanity, and finally realized I forgot the empty function.

A fabulous fantastic mechanism that would have saved me some time is simply coloring the clauses of the template constraint that failed red, the ones that passed green, and the ones that weren't evaluated grey.

Furthermore, it would be good to either recursively continue this for red clauses like `hasSlicing` which have so much underneath. Either that or a way to trigger the colored evaluation on demand.

If I were a dmd guru, I'd look at doing this myself. I may still try and hack it in just to see if I can do it.

------

Finally, there is a possible bug in the definition of hasSlicing: it doesn't require the slice parameters be size_t, but there are places (e.g. inside std.algorithm.searching.find) that pass in range.length .. range.length for slicing the range. In my implementation I had used ints as the parameters for opSlice. So I started seeing errors deep inside std.algorithm saying there was no overload for slicing. Again the sanity was questioned, and I figured out the error and now it's actually working.

-Steve

Reply via email to