The new, new phobos sneak preview

Daniel Keep daniel.keep.lists at gmail.com
Sun Apr 12 22:58:58 PDT 2009


Looking at the documentation, I found std.range.isForwardRange.  I had a
look at the implementation, and it basically just checks to make sure
you can do this:

> R r1;
> R r2 = r1;

How do you construct an input range which is not also a forward range?
For structs, you can't prevent that second line from working, except by
throwing an exception in postblit (which the test won't notice).  For
classes, you have no control over direct assignment.

Here's a practical example: I'm playing with a program that will parse
the output of DMD to find out module imports.  I want to expose this
list of imports as a range.  However, this range is NOT resumable since
you can't seek a program's captured stdout backwards; copying the file
handle certainly isn't going to work...

You could probably do it by making sure the range is a struct pointing
to a class which can then take its internal file handle and re-assign it
to a split buffered stream... but I'm never going to use it like that,
so why should I go through all that effort?

Aside from making it possible to forbid assignment (blech), it seems
like there needs to be a way to flag a range as not supporting resuming.
 The only reasonable way I can think of off the top of my head would be
something like this:

> template isResumableRange(R)
> {
>     enum bool isResumableRange = isInputRange!(R)
>         && (is(typeof(R.isResumableRange)) && R.isResumableRange)
>         && is(typeof(
>         {
>             R r1;
>             R r2 = r1;
>         }()));
> }
>
> unittest
> {
>     static assert(!isResumableRange!(int));
>     static assert(isResumableRange!(int[]));
>
>     struct A {}
>     struct B
>     {
>         void next();
>         bool empty();
>         int head();
>     }
>     struct C
>     {
>         static enum isResumableRange = true;
>         void next();
>         bool empty();
>         int head();
>     }
>     struct D
>     {
>         static enum isResumableRange = false;
>         void next();
>         bool empty();
>         int head();
>     }
>     static assert(isResumableRange!(A));
>     static assert(isResumableRange!(B));
>     static assert(isResumableRange!(C));
>     static assert(isResumableRange!(D));
> }

I also took the opportunity to rename isForwardRange to isResumableRange
since I can't see how the ability to make a "checkpoint" has anything to
do with being able to go forward.  For example isBidirectionalRange
requires isForwardRange, but what does saving checkpoints have to do
with being able to go in both directions?

  -- Daniel



More information about the Digitalmars-d mailing list