When expensive_call can return zero for a valid value or return undef to indicate failure, use the

D'Orcish Maneuver

my @sorted = sort { ( $times{$a} //= expensive_call($a) ) <=> ( $times{$b} //= expensive_call($b) ) } @old_array;
defined-or cache, needs defined-or (dor) operator introduced in 5.10

See also Resorting to Sorting, Sorting problem with Orcish Manuever

Replies are listed 'Best First'.
Re: D'Orcish Maneuver
by Your Mother (Archbishop) on Apr 27, 2011 at 21:21 UTC

    Oh, please, everyone! Spell it "dorkish." For me. I ask for so little.

Re: D'Orcish Maneuver
by ikegami (Patriarch) on Apr 27, 2011 at 21:52 UTC

    Dorkish indeed. I don't see how that makes any sense.

    First, it gives tons of warnings. Second, it doesn't make sense to treat an error signal as a valid value.

    $ perl -wE' sub expensive_call { $_[0] == -1 ? undef : $_[0] } say $_ // "[undef]" for sort { ( $c{$a} //= expensive_call($a) ) <=> ( $c{$b} //= expensive_call($b) ) } 0,1,-1,-1,0,2; ' Use of uninitialized value $c{"-1"} in numeric comparison (<=>) at -e +line 3. Use of uninitialized value $c{"-1"} in numeric comparison (<=>) at -e +line 3. Use of uninitialized value $c{"-1"} in numeric comparison (<=>) at -e +line 3. Use of uninitialized value $c{"-1"} in numeric comparison (<=>) at -e +line 3. Use of uninitialized value $c{"-1"} in numeric comparison (<=>) at -e +line 3. Use of uninitialized value $c{"-1"} in numeric comparison (<=>) at -e +line 3. Use of uninitialized value $c{"-1"} in numeric comparison (<=>) at -e +line 3. 0 -1 -1 0 1 2

    It would make more sense to handle the error, perhaps by dying or by using a sensible default.

    $ perl -wE' sub expensive_call { $_[0] == -1 ? undef : $_[0] } say $_ // "[undef]" for sort { ( $c{$a} ||= expensive_call($a) // -1 ) <=> ( $c{$b} ||= expensive_call($b) // -1 ) } 0,1,-1,-1,0,2; ' -1 -1 0 0 1 2
      Well, duh. Of course it gives a ton of warnings. But that's not the fault of the orkish maneuver - it's the fault of the set of elements you want to sort. You'd get the same warnings if you'd used a plain sort, or an ST - the warnings come from returning undefined values in the function that maps elements to sort to <=> operands.
      #!/usr/bin/perl use 5.010; use strict; use warnings; sub expensive_call { $_[0] == -1 ? undef : $_[0] } say $_ // "[undef]" for sort {expensive_call($a) <=> expensive_call($b +)} 0,1,-1,-1,0,2; __END__ Use of uninitialized value in numeric comparison (<=>) at /tmp/s line +9. Use of uninitialized value in numeric comparison (<=>) at /tmp/s line +9. Use of uninitialized value in numeric comparison (<=>) at /tmp/s line +9. Use of uninitialized value in numeric comparison (<=>) at /tmp/s line +9. Use of uninitialized value in numeric comparison (<=>) at /tmp/s line +9. Use of uninitialized value in numeric comparison (<=>) at /tmp/s line +9. Use of uninitialized value in numeric comparison (<=>) at /tmp/s line +9. 0 -1 -1 0 1 2
      I complete fail to get the point you're trying to make.

        You'd get the same warnings if you'd used a plain sort, or an ST

        So just use those, then. The whole point of the OP's code is that it's suppose to be able to handle undef. Since it doesn't, it's a bug.

Re: D'Orcish Maneuver
by John M. Dlugosz (Monsignor) on Apr 30, 2011 at 10:28 UTC
    Your point being that we can now use //= instead of ||= for this construct?

    Kind of lame for a Meditation, I think. In fact, isn't that an example under the explainations of the new operator?

Re: D'Orcish Maneuver
by locked_user sundialsvc4 (Abbot) on Apr 29, 2011 at 02:30 UTC

    It is clever.   To that end, thank you for introducing it to us.   But let us simply acknowledge that it does have its potential deficiencies ... as all potentially-useful “clever things” always do.

      But let us simply acknowledge that it does have its potential deficiencies

      Really? Could you outline those potential deficiencies for us?

      One potential deficiency?