On 06/22/2013 09:08 PM, monarch_dodra wrote:
> Personally, I've found ranges to be a very useful and powerful *high level*
> abstraction. They lend themselves work very well for adapting and chaining
> (which iterators don't). However, they do come with *some* downsides (IMO):
> #1: Performance issues: No matter how I use them, it seems that I can never 
> get
> the same raw performance I could get with raw iterator iteration.*

Do you think that's inevitable?  I'd have thought that this ought to be possible
to improve with better compiler optimizations.

> *: #1 is subject to simple iteration: Once things scale in terms of adaptors,
> ranges win because of the "single item empty" mechanic

Could you explain that in a bit more depth, please?

> #2: Extremelly bad compatibility with simple no bidir/non-slicing ranges: 
> There
> is no way to iterate over a specific part of a range, and making a range out 
> of
> what was just iterated over. For example "Get the beggining of this range 
> until
> the first x": not possible without slicing.

Not sure what you mean here -- doesn't the attached little code example do
roughly what you're looking for?  (N.B. it has crap template constraints.
Typing this quickly I couldn't work out how to make sure that the second
constructor argument matches the type of input.front.)
import std.range;

struct UntilFirst(R, T)
    if(isInputRange!R)
{
    private R _input;
    private T _x;

    this(R input, T x)
    {
        _input = input;
        _x = x;
    }

    bool empty() @property
    {
        return _input.empty || _input.front == _x;
    }

    auto front() @property
    {
        assert(!empty);
        return _input.front;
    }

    void popFront()
    {
        assert(!empty);
        _input.popFront();
    }
}

auto untilFirst(R, T)(R input, T x)
    if(isInputRange!R)
{
    return UntilFirst!(R, T)(input, x);
}

unittest
{
    import std.stdio;
    writeln(untilFirst(iota(20), 13));
    writeln(untilFirst("abcdefghijklmnopqrstuvwxyz", 'j'));
}

Reply via email to