digitalmars.D.learn - Function called twice
- Jordan Wilson (22/22) Aug 02 2019 Hello,
- Adam D. Ruppe (10/14) Aug 02 2019 I *think* what's happening here is first it calls map() first
- Jordan Wilson (5/20) Aug 02 2019 In my real-world case "isEven" is a long running function. I'll
- Boris Carvajal (9/31) Aug 02 2019 The way map is designed is to call its predicate on each front
- Simen =?UTF-8?B?S2rDpnLDpXM=?= (13/33) Aug 02 2019 map doesn't memoize its front value
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; } Thanks, Jordan
Aug 02 2019
On Friday, 2 August 2019 at 21:44:28 UTC, Jordan Wilson wrote:// outputs 1 2 2 3 z.map!(a => tuple!("number","iseven")(a, a.isEven)) .filter!(a => a.iseven) .array;I *think* what's happening here is first it calls map() first going into the filter... then it gets called again when it is being evaluated for the array. So like basically consider if you had: if(filter(a()) array ~= a(); that kind of thing. I think anyway, I'm not entirely sure but it fits what I can see happening here. but idk why it is actually doing this in the phobos implementation
Aug 02 2019
On Friday, 2 August 2019 at 22:35:53 UTC, Adam D. Ruppe wrote:On Friday, 2 August 2019 at 21:44:28 UTC, Jordan Wilson wrote:In my real-world case "isEven" is a long running function. I'll put an .array after the map and see if it makes a difference. Thanks, Jordan// outputs 1 2 2 3 z.map!(a => tuple!("number","iseven")(a, a.isEven)) .filter!(a => a.iseven) .array;I *think* what's happening here is first it calls map() first going into the filter... then it gets called again when it is being evaluated for the array. So like basically consider if you had: if(filter(a()) array ~= a(); that kind of thing. I think anyway, I'm not entirely sure but it fits what I can see happening here. but idk why it is actually doing this in the phobos implementation
Aug 02 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; } Thanks, JordanThe way map is designed is to call its predicate on each front call and filter calls it twice with the number 2. https://github.com/dlang/phobos/blob/master/std/algorithm/iteration.d#L604 You can use "cache" to avoid the double front call on any range. z.map!(a => tuple!("number","iseven")(a, a.isEven)) .cache .filter!(a => a.iseven) .array;
Aug 02 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
Aug 02 2019