Map, filter and pure functions

Paul Backus snarwin at gmail.com
Fri Nov 29 15:49:24 UTC 2019


On Friday, 29 November 2019 at 15:30:22 UTC, realhet wrote:
> Hi,
>
> I have an input range.
> I use the map! on it to transform using a function.
> Finally I use filter! on the transformed data.
>
> When I do a foreach on this, i noticed, that the transform 
> function is called twice for each element.
> If I remove the filter! it does only one transform function 
> call per element.
>
> Is this because the function is NOT PURE, so Phobos thinks that 
> the function can give different results for the same input?
>
> If I modify the function to be pure, will the transform 
> function be called only once?

It's actually a much simpler reason: filter calls .front twice 
for each element in its input (once to check if the value 
satisfies the predicate, and then again to return the value if it 
does), and the range returned by map doesn't save the value of 
.front between calls, so it has to re-compute it each time by 
calling the transform function.

You can work around this using std.algorithm.iteration.cache, a 
range wrapper that calls .front on the underlying range exactly 
once, and then saves the value and reuses it for subsequent calls:

myRange
     .map!transform
     .cache
     .filter!pred
     .each!doSomething;


More information about the Digitalmars-d-learn mailing list