The last changes to range

Pelle pelle.mansson at gmail.com
Sun May 30 03:43:03 PDT 2010


On 05/30/2010 12:11 PM, Philippe Sigaud wrote:
> On Sat, May 29, 2010 at 23:30, Andrei Alexandrescu
> <SeeWebsiteForEmail at erdani.org <mailto:SeeWebsiteForEmail at erdani.org>>
> wrote:
>
>     On 05/29/2010 03:05 PM, Philippe Sigaud wrote:
>
>
>         Does that mean that you changed some other parts recently?
>
>
>     Not recently, I think I made the last changes before you joined the
>     gang.
>
>
> OK, I wondered whether std.container had reverberations I wasn't aware of.
> Btw, I plan to play with trees and graphs and algorithms on them. I will
> modify my code to respect your container interface and see what sticks.
>
>
>             1. First, I want to define this:
>
>             // inside range type SomeRange
>             @property SomeRange save();
>
>
>         vote++
>         That should make it clear you need a forward range for an algorithm.
>
>
>     Yah.
>
>
> Will the definition of a forward range change to incorporate save, or do
> you intend to distinguish ranges that can do
>
>      R r2 = r1;
> and those that have:
>      auto r2 = r1.save;
> ?
> Until now, they were one and the same to me.
>
>
>             The idea is that save() provides a guaranteed means to take a
>             snapshot in a range's state. The notable absents are input
>         ranges -
>             they are unable to define save(), and therefore some algorithms
>             won't apply to them.
>
>
>         I think many ranges and algorithm that you put in std have a
>         constraint
>         on InputRange that should be changed to ForwardRange. Most
>         (all?) of the
>         lazy ones should probably ask for a ForwardRange. Don't forget
>         to update
>         that part.
>
>
>     I'm not sure about that. Could you give an example? Why would map()
>     not work with an input range?
>
>
> Because you make a copy of the input range in Map's constructor?
>
> this(Range input) { _input = input; fillCache; }
>
> I supposed _input = input was not possible with an input range? It's the
> very definition of a forward range, no?
>
> An eager version of map could use an InputRange as input:
>
> template eagerMap(alias fun)
> {
>      typeof(unaryFun!fun(ElementType!R.init))[] eagerMap(R)(R r) if
> (isInputRange!R && !isInfinite!R)
>      {
>          typeof(unaryFun!fun(ElementType!R.init))[] mapped;
>          static if (hasLength!R)
>          {
>              mapped.length = r.length;
>              foreach(i, elem; r) mapped[i] = unaryFun!fun(elem);
>          }
>          else
>          {
>              foreach(elem; r) mapped ~= unaryFun!fun(elem); // maybe
> with an ArrayAppender?
>          }
>          return mapped;
>      }
> }
>
>             2. swapFront, swapBack, and swapAt methods
>
>             // inside range type SomeRange
>             void swapFront(ref ElementType!SomeRange obj);
>             void swapBack(ref ElementType!SomeRange obj);
>             void swapAt(size_t i, ref ElementType!SomeRange obj);
>
>     They will be methods because they must be primitive operations of
>     the respective ranges. However, there will be wrappers like this:
>
>     // at module scope
>     void swapFront(Range)(Range r1, Range r2)
>     {
>         static if (is(typeof(&(r1.front)) == ElementType!(Range)*)) {
>             swap(r1.front, r2.front);
>         } else {
>             static assert(is(typeof(&(r1.swapFront)), "Cannot swap ranges");
>             r1.swapFront(r2);
>         }
>     }
>
>
> OK. I really like this possibility to test for members and activate them
> when possible. Maybe it could be abstracted away into a Select-like
> template?
>
>
>             3. sameFront()
>
>             The gnarly bringToFront() algorithm needs the primitive:
>
>             // inside range type SomeRange
>             bool sameFront(SomeRange another);
>
>             I think it's necessary for future algorithms as well. It's an
>             optional primitive. In particular, if front() returns by
>         reference
>             it's easy to infer that two ranges have the same front by
>         comparing
>             the addresses of their front()s.
>
>         And if front does not return by ref? Do you then define the
>         fronts to be
>         different or compare the values?
>
>
>     If front() does not return by ref, the range should define
>     sameFront() as a member. If it doesn't, it won't have access to a
>     number of algorithms.
>
>
> OK. So it's really sameFront and not equalFront or somesuch.
>
>
>
>         About returning by ref, did you try to use 'auto ref'? I think I
>         tried
>         the day the feature appeared, without success, IIRC. Many ranges in
>         Phobos return by ref and won't compose with other ranges because
>         of that.
>
>
>     Yah, auto ref was meant for that kind of work. But generally note
>     that certain ranges actively refuse to return by ref in order to not
>     expose addresses of their elements. Such ranges are fit for
>     perfectly encapsulated containers.
>
>
> I was thinking of frustrating obstacles like:
>
> auto m = map!"a*a"([0,1,2,3]);
> auto c = cycle(m); // won't compile, m.front is not an lvalue, whereas
> c.front asks for one.

Worse:

string r = "ab";
auto c = cycle(r); // doesn't compile.


More information about the Digitalmars-d mailing list