RFC on SlidingSplitter Range
monarch_dodra via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Fri Oct 3 10:46:16 PDT 2014
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", "")
More information about the Digitalmars-d-learn
mailing list