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