Orcish Maneuver
ALIAS: OM, Orcish Manoeuvre
There is an inline cache technique called the Orcish Maneuver, a clever pun on Orc (perhaps) and “OR Cache”. Joseph Hall (author of “Effective Perl Programming”) coined the term.
It is useful for caching inside the sort comparator function to increase speed. Joseph uses a hash to store the potentially expensive sort value. If that key does not yet exist, he calculates and stores it for next time.
$cache{$a} ||= function($a); # If it is not cached, $cache{$a} is false
# function() is called
# the result is stored in the cache
# the result is returned
This idiom relies on the feature that a Perl assignment returns the value assigned.
my %cache;
my @sorted = sort {
( $cache{$a} ||= function($a) )
<=>
( $cache{$b} ||= function($b) )
} @old_array;
It is better using the defined-or operator if empty string or 0 values are returned by the function:
my %cache;
my @sorted = sort {
( $cache{$a} //= function($a) )
<=>
( $cache{$b} //= function($b) )
} @old_array;
CAVEATS
It has some minor efficiency flaws:
- An extra test is necessary after each sortkey is retrieved from the or-cache.
- If an extracted sortkey has a false value, it will be recomputed every time. This is not usually the case, because the extracted sortkeys are seldom false.
Comparison
Except when the need to avoid reading the data twice is critical, the explicit cached sort is always slightly faster than the OM.
It is simpler than Schwartzian Transform and faster, if the list contains duplicates.