On Tuesday, 26 June 2012 at 06:05:49 UTC, Jonathan M Davis wrote:
If you can't calculate the length in O(1), then you're stuck using walkLength, which means iterating over the entire range to get its length. And if that's the case, then you can't make it a random access range, because for it to be a random access range, it either needs to have a length property (which must be O(1)) or be infinite. And I would fully expect for your code to run into a variety of bugs if you tried to claim that it was a length that it wasn't (e.g. ulong.max), since a number of functions will expect that that's its
actual length and won't work properly if it's not.

For a range to be random access, it must fulfill these requirements:

template isRandomAccessRange(R)
{
    enum bool isRandomAccessRange = is(typeof(
    (inout int _dummy=0)
    {
        static assert(isBidirectionalRange!R ||
                      isForwardRange!R && isInfinite!R);
        R r = void;
        auto e = r[1];
        static assert(!isNarrowString!R);
        static assert(hasLength!R || isInfinite!R);
    }));
}

and I'm not sure that you can squeeze your range into that. You could do it if you just read in the entire range and created another range from it (be it an array or whatever), but you appear to be attempting something which probably won't quite work with the current range design. I suspect that you'd do better trying to claim that it wasn infinite rather than had a length, but then you'd have to be able to deal with the fact that empty is always false.

- Jonathan M Davis

I actually only needed length() because random access ranges required it (not because I did), but maybe I can avoid it some way without using random access ranges at all... I'll try to rework stuff. Thanks for the explanations.

Reply via email to