[phobos] is*Range + Qualified Types

Steve Schveighoffer schveiguy at yahoo.com
Thu Aug 12 05:52:33 PDT 2010

----- Original Message ----

> From: Shin Fujishiro <rsinfu at gmail.com>
> David Simcha <dsimcha at gmail.com> wrote:
> > I'm  looking to go on a major debugging spree and make std.range work 
> > with  const ranges.  For example, the following should work:
> > 
> >  import std.range, std.algorithm;
> > 
> > void main() {
> >       const foo = map!"a ^^ 2"([1,2,3,4,5]);
> >       auto myRetro = retro(foo);
> > }
> Could you elaborate  why?
> Ranges with const elements must be common; but what's the point  of
> const ranges?  Const random access ranges are usable, but other  const
> ranges seem to be useless since popFront and popBack can't be  const.

This seems to point at a larger issue.

With the de-facto range T[], we get an implicit cast to a range of const 
elements, const(T)[].

But we cannot get this with any user-defined type.  I think we will need to 
address this eventually.  It's one of the main reasons dcollections is not 
const-aware, because I don't want to create several types of ranges/cursors, and 
then all the duplicated functions that go with it.  I'd rather use inout and 
have it designate the return type.

I think Janice proposed something a long long time ago that allowed a template 
parameter to represent a const factor of a type, a-la:

    struct node
       V value;
       node *next;
    node *head;

    struct range(const C)
        C(node)* cur;
        @property C(V) front() {return cur.value;}
        void popFront() {next = cur.next;}
        @property bool empty() {return next !is null;}

    range!(inout) opSlice() inout {range!(inout) result;  result.cur = head; 
return result;}

So basically, the way it works is C is substituted for a const factor (const, 
immutable, or nothing).  And more importantly, the compiler allows implicit 
conversion from a range!(???) to a range!(const).  Also, we can apply inout 
rules.  (Note, I don't know what to put as a const parameter for mutable, since 
that's not a keyword, hence the ???).

Does this seem complex?  Yes.  But it's not as complex/hard to read/hard to 
implement as 3 copies of all functions with 3 different range types.  It's akin 
to the savings/clarity of inout.

What I'm unsure about is if we need to do it this way.  I don't like using a 
user-defined parameter as the const factor, it makes it #1 hard to read, and #2 
every person's const factor symbol may be different.  Most likely, you will have 
one const template parameter.  Do we need to support multiple parameters?  inout 
avoids requiring templates, because the code generation is identical.  Can we do 
something similar to inout?

We're going to need something like this to avoid rediculous code repetition for 
any type that uses custom range types.  Essentially what we need to duplicate is 
the "apply const only to one member" feature of builtin arrays.



More information about the phobos mailing list