Doing my own deeds, I often found myself in need of writing up a range just to 
e.g. feed it into an algorithm. Problem is, defining even the simplest range -- 
one-pass forward -- is verbose enough to render this (correct) approach 
unprofitable.

This is how I went about the problem:

auto range(T, Whatever)(lazy bool _empty, lazy Whatever _popFront, lazy T 
_front) {
    struct AdHocRange {
        @property bool empty() { return _empty(); }
        void popFront() { _popFront(); }
        @property T front() { return _front(); }
    }
    return AdHocRange();
}

--- example ---

try { ... }
catch(Throwable t)
{
    auto r = range(t is null, t = t.next, t);

    // process exception chain...
}

I don't know a terser way to get a full-fledged range. It comes at a cost, 
though. Lazy parameters are just sugar over delegates, so it's not exactly 
Usain Bolt**... And you can't return it because by bug or by design lazy 
parameters (unlike vanilla delegates) don't work like closures. Still, even 
with the overhead and limitations the idiom is remarkably useful, especially in 
face of range-unfriendly libraries from outside D realm.

Enjoy.

-- 
Tomek

** Of course, there exists a somewhat more verbose compile-time variant of the 
idiom I presented.

Reply via email to