Hi llavaud, welcome to the monastery. I'm glad that you got it, but feel free to ask if you need more details.
| [reply] |
thanks,
just another small thing, i read that foreach is more efficient than map, but i can't adapt your code to use it with the sum, maybe it is not possible ?
| [reply] [d/l] [select] |
Well, most of the time foreach and map do different things, so I don't know about that. Maybe for (@in) { push @out, op($_); } is faster than @out = map { op($_) } @in;, but I think what you read might have been about the use of map as a substitute for for, as in ; map { $_ *= 2 } @list; instead of ; $_ *= 2 for @list;. You might read that it's bad practice because map builds a new list which is thrown away (people will tell you not to use map in void context). I think it is bad practice because map is supposed to turn a list into another, so the intent is clearer in the second case.
And to answer your question, since for can't be a sub expression (you shouldn't use the return value of a for loop), but the looping part is the inner part of the logic (the outer part being to choose between the cache and a new computation), to use the for loop, you need to extract the if/else logic out. $sum = $cache{$inner} //= sum map { $_->{value} } @{ $foo->{$inner} }{@keys}; becomes:
unless (exists $cache{$inner})
{
$cache{$inner} = 0;
$cache{$inner} += $_->{value} for @{ $foo->{$inner} }{@keys};
# This might be a little faster, because perl doesn't have to build
+the temporary list @{ $foo->{$inner} }{@keys}
# $cache{$inner} += $foo->{$inner}{$_}{value} for @keys;
}
$sum = $cache{$inner};
This version is also a little more correct, because it uses exists instead of defined (implicit with //) for the cache. | [reply] [d/l] [select] |