Help with Ranges

Steven Schveighoffer schveiguy at gmail.com
Sun Jul 26 14:56:35 UTC 2020


On 7/26/20 3:10 AM, Charles wrote:
> Suppose I have the following line of code where arr is an array, 
> doSomething is some predicate that does a lot of processing on each 
> element, sort must come after the mapping, and there are more operations 
> done to the range after sort:
> 
> arr.map!doSomething.sort. ...;
> 
> Sort fails to instantiate because the range it's receiving doesn't 
> support element swapping. This may and might be resolved by calling array:
> 
> arr.map!doSomething.array.sort. ...;
> 
> However, this might trigger an allocation, and there's still more to do! 
> Is there something I'm missing with regards to ranges that could help me 
> make the first line work without using array, or is it more of an issue 
> with my code's design?

That is what you need to do.

A map that returns an lvalue would be sortable, but you would be sorting 
the processed elements, and probably not the original elements.

I have found this handy tool quite useful in my code where I need a 
temporary array:

// creates a concrete range (std.container.array.Array range) out of the
// original range that is eagerly fetched, and then can be processed, 
without
// allocating extra garbage on the heap.
auto concreteRange(Range)(Range r)
{
     import std.range : ElementType;
     import std.container.array : Array;
     return Array!(ElementType!Range)(r)[];
}

Slicing an Array will keep the reference count correctly, and destroy 
the memory automatically after you're done using it. So it's perfect for 
temporary arrays in pipelining.

-Steve


More information about the Digitalmars-d-learn mailing list