On Friday, 3 October 2014 at 17:06:41 UTC, Nordlöw wrote:
On Friday, 3 October 2014 at 16:32:24 UTC, monarch_dodra wrote:
If anything, I'd have expected you to provide something returns the popped element. What you do pops an element, and then returns the *next* one. What good is that?

My mistake. It's fixed now.

Well, yes and no. You are still providing a moveFront that does not conform to what the range interface expects. EG:

auto app = appender();
auto myRange = slidingSplitter([1, 2, 3]);
for ( ; !myRange.empty ; myRange.popFront() )
  app.put(myRange.moveFront());

As you can see from this code snippet, moveFront is not expected to pop. At all. As a matter of fact, this will error out during runtime, as the loop will attempt a pop on an empty range.

IMO, you should just leave it out.

Also, what you want to check is "hasSlicing", which is more powerful than "isRA". Speaking of which, if you don't have "isRA", it looks like your range errors out (no "front").

Ok. Fixed know.

There's still the issue that if you don't have slicing, then your range doesn't have "front" at all. You might as well just make it a general template restriction.

Your sliding splitter does not handle narrow strings. I'd have thought that was the original goal. Well, it is better to not support it at all of course, rather than doing it wrong :)

That's part of episode 2, for now ;)

Cool.

More things I saw:
Don't make opIndex const. You have no guarantee R.opindex is const. Also, "opSlice()" is not a range primitive. You can implement it, it's basically just a no-op. The one that's important is "opSlice(lhs, rhs)".

Also, no point in returning an "auto ref" from "slidingSplitter", you *know* it's an rvalue.

If your implementation use two ranges that you slice "on the fly", then you can trivially support strings, thanks to popFront.

I threw this together. I left out checks for infinity in favor of brevity:

//----
import std.range, std.stdio;
import std.typecons: Tuple, tuple;

struct SlidingSplitter(R)
if (hasSlicing!R || isSomeString!R)
{
    this(R)(R data)
    {
        _original = data;
        _right = data.save;
    }

    auto front() @property
    {
        return tuple(_original[0 .. $ - _right.length], _right);
    }

    void popFront()
    {
        if (_right.empty)
            _original = _right;
        else
            _right.popFront();
    }

    bool empty() const { return _original.empty; }

    static if (hasSlicing!R)
    {
        auto opIndex(size_t i)
        {
            return tuple(
                _original[0 .. i + $ - _right.length],
                _right[i .. $]);
        }

        size_t length() { return _right.length + 1; }
    }

    private R _original;
    private R _right;
}

auto slidingSplitter(R)(R data)
{
    return SlidingSplitter!R(data);
}

void main()
{
    {
        auto r = slidingSplitter([1, 2, 3]);
        writefln("r.length: %s", r.length);
        writefln("r[1]: %s", r[1]);
        writefln("r[2]: %s", r[2]);
    }
    {
        writefln("%(%s\n%)", slidingSplitter("Nordlöw"));
    }
}
//----

Output:

r.length: 4
r[1]: Tuple!(int[], int[])([1], [2, 3])
r[2]: Tuple!(int[], int[])([1, 2], [3])
Tuple!(string, string)("", "Nordlöw")
Tuple!(string, string)("N", "ordlöw")
Tuple!(string, string)("No", "rdlöw")
Tuple!(string, string)("Nor", "dlöw")
Tuple!(string, string)("Nord", "löw")
Tuple!(string, string)("Nordl", "öw")
Tuple!(string, string)("Nordlö", "w")
Tuple!(string, string)("Nordlöw", "")

Reply via email to