Flatten a range of static arrays

Steven Schveighoffer schveiguy at gmail.com
Fri Feb 7 20:31:47 UTC 2020


On 2/7/20 3:13 PM, Dennis wrote:
> If I have an input range with element type `int[3]`, how do I easily 
> turn it into a range of `int` so I can map it?
> If it were an int[3][] I could simply cast it to an int[] before 
> mapping, but I don't want to eagerly turn it into an array.
> I thought of doing this:
> ```
> range.map!(x => x[]).joiner.map!(x => x*2);
> ```
> 
> But it gives:
> Error: returning x[] escapes a reference to parameter x, perhaps 
> annotate with return

This is correct. Consider that you did not mark x as ref. So what x 
actually is is a function local. If you returned x[], you just returned 
a reference to a local, which is about to go out of scope.

> I tried doing:
> ```
> map!((return x) => x[]) // same error
> map!((return ref x) => x[]) // does not match, map.front is not an lvalue
> ```
> 
> I can easily work around it with some more code, but I wonder if someone 
> knows an easy solution.

This means your actual input range is not an array (map should forward 
the lvalueness of it). This means you can't just slice, as you will 
again return references to the local stack frame.

The only solution I can provide is to wrap the static array into a range 
(maybe something like this exists in Phobos?):

struct SARange(T, size_t N)
{
    T[N] storage;
    size_t elem;
    auto front() { return storage[elem]; }
    void popFront() { ++elem; }
    bool empty() { return elem >= N; }
}

auto asRange(T : E[N], E, size_t N)(T val) {
    return SARange!(E, N)(val);
}

range.map!(x => x.asRange).joiner.map!(x => x*2);

-Steve


More information about the Digitalmars-d-learn mailing list