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

ok i think i got it, finally it is not so hard to understand, i am just not familiar with the "slice" form @{ $foo->{$b_} }{@keys}.

thanks for your help !

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

    Hi llavaud, welcome to the monastery. I'm glad that you got it, but feel free to ask if you need more details.

      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 ?

        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.