Function called twice

Simen Kjærås simen.kjaras at gmail.com
Fri Aug 2 22:54:56 UTC 2019


On Friday, 2 August 2019 at 21:44:28 UTC, Jordan Wilson wrote:
> Hello,
>
> I don't quite understand why isEven is called twice in the 2nd 
> example?
>
> auto isEven(int n) {
> 	n.writeln;
> 	return (n % 2) == 0;
> }
>
> void main() {
>
> 	auto z = [1,2,3];
> 	
> 	// outputs 1 2 3
> 	z.map!(a => tuple!("number")(a))
> 	 .filter!(a => a.number.isEven)
> 	 .array;
>
> 	// outputs 1 2 2 3
> 	z.map!(a => tuple!("number","iseven")(a, a.isEven))
> 	 .filter!(a => a.iseven)
> 	 .array;
>
> 	return;
> }

map doesn't memoize its front value 
(https://github.com/dlang/phobos/blob/master/std/algorithm/iteration.d#L604), so every time someone looks at it the mapping function needs to be called again. So in the second case, for each item first filter calls map.front which calls isEven, then if it matches the filter (so only the 2), array calls filter.front, which calls map.front, which calls isEven.

You can avoid this by eagerly iterating to an array:

     z.map!(a => tuple!("number","iseven")(a, a.isEven))
         .array // new!
         .filter!(a => a.iseven)
         .array;

I was also gonna suggest using std.functional.memoize to memoize 
the function in map, but apparently it doesn't like lambdas 
(https://issues.dlang.org/show_bug.cgi?id=20099).

--
   Simen


More information about the Digitalmars-d-learn mailing list