Language Idea #6892: in array ops, enable mixing slices and random access ranges

Simen Kjærås simen.kjaras at gmail.com
Tue Feb 6 09:02:46 UTC 2018


On Tuesday, 6 February 2018 at 02:14:35 UTC, Meta wrote:
>> What do you think?
>
> It's already possible, with only very slightly worse aesthetics:
>
[Good stuff]

We can do better than that, though:

import std.range, std.array, std.algorithm;

struct Vec(Range)
if (isInputRange!Range)
{
     Range rng;

     this(Range value)
     {
         rng = value;
     }

     static if (!isInfinite!Range)
     {
         auto get()
         {
             return rng.array;
         }
         alias get this;
     }

     auto getRange(R2)(R2 other)
     {
         static if (isInputRange!R2)
             return other;
         else static if (isVec!R2)
             return other.rng;
         else
             return repeat(other);
     }

     auto opBinary(string op, R2)(R2 rhs)
     {
         return vec(rng.zip(getRange(rhs)).map!("a[0] "~op~" 
a[1]"));
     }

     auto opBinaryRight(string op, R2)(R2 lhs)
     {
         return vec(getRange(lhs).zip(rng).map!("a[0] "~op~" 
a[1]"));
     }

     auto opOpAssign(string op, R2)(R2 rhs)
     if (isForwardRange!Range)
     {
         auto rhsR = getRange(rhs);

         auto r = rng.save;
         foreach (ref e; r)
         {
             if (rhsR.empty) break;
             mixin("e "~op~"= rhsR.front;");
             rhsR.popFront();
         }
         return this;
     }
}

auto vec(Range)(Range r)
if (isInputRange!Range)
{
     return Vec!Range(r);
}

enum isVec(T) = is(T == Vec!U, U);

unittest
{
     import std.stdio;
     auto a = [1,2,3,4,5,6,7,8];
     auto b = a.length.iota;
     auto c = recurrence!("a[n-1] + a[n-2]")(1, 1);

     uint[] result = a + b * c.vec;
     writeln(result);
     result.vec += result;
}

--
   Simen


More information about the Digitalmars-d mailing list