in reply to Re^3: Optimize a perl block
in thread Optimize a perl block

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 ?

Replies are listed 'Best First'.
Re^5: Optimize a perl block
by Eily (Monsignor) on Sep 08, 2017 at 10:31 UTC

    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.

      i have tried that and $cache{$inner} += $_->{value} for @{ $foo->{$inner} }{@keys}; is slightly slower than $cache{$inner} += $foo->{$inner}{$_}{value} for @keys; but both are slower (just about 1s) than map, so i will stay with your first version !

      now my code run in 12s instead of 30s with my version, i would not have hoped for such optimization, Perl and YOU are magic ! ;)