vit has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks,
is there a possibility to store operation as some string. Basically I want to be able to change "sort" content on condition.
foreach ( sort { $scores{$b} <=> $scores{$a} } keys %scores )
Of couse I can write a sub, but I need to do it nice, something like:
$expr = (CONDITION) ? "$scores{$b} <=> $scores{$a}" : $scores{$a} <=> +$scores{$b}
I am making it up of course, just to explain what I want.

Replies are listed 'Best First'.
Re: Store operation in a variable
by Utilitarian (Vicar) on Aug 03, 2010 at 20:49 UTC
    Perhaps what you need is a dispatch table.
    for my $score (sort { &{ $dispatch{$condition} } } keys %scores){ ...
    Then have a sub for each possible condition.

    print "Good ",qw(night morning afternoon evening)[(localtime)[2]/6]," fellow monks."
Re: Store operation in a variable
by BrowserUk (Patriarch) on Aug 03, 2010 at 21:12 UTC

    Rather than burdening every comparison of the sort with a conditional test, it'll be more efficient to sort the keys to an array and then reverse the array conditionally:

    my @sorted = sort { $scores{$b} <=> $scores{$a} } keys %scores; @sorted = reverse @sorted if condition; for ( @sorted ) { ... }

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Store operation in a variable
by kennethk (Abbot) on Aug 03, 2010 at 21:01 UTC
    One solution would be to use an eval. This is a little clever/possibly fragile for my taste, but quite literally does what you want:

    #!/usr/bin/perl use strict; use warnings; my $condition; my %scores = (Jim => 98, Mike => 82, Bill => 91, Joe => 61, ); my $expr = $condition ? '$scores{$b} <=> $scores{$a}' : '$scores{$a} < +=> $scores{$b}'; print join "\n", sort {eval $expr} keys %scores;

    A more natural choice would be to just use sort's natural ability to take a subroutine/code ref as an argument:

    #!/usr/bin/perl use strict; use warnings; my $condition; my %scores = (Jim => 98, Mike => 82, Bill => 91, Joe => 61, ); my $code_ref = sub { if ($condition) { $scores{$b} <=> $scores{$a}; } else { $scores{$a} <=> $scores{$b}; } }; print join "\n", sort $code_ref keys %scores;

    I've used a closure above - if you are not familiar with them, perhaps a read-through of perlfaq7's What's a closure? would be helpful.

Re: Store operation in a variable
by aquarium (Curate) on Aug 04, 2010 at 01:32 UTC
    can you rephrase the question?..difficult to tell if you're after a dispatch table OR a sort if and only if a condition is met OR if you're attempting to change sorting operation mid-stream OR something else. Perhaps a bit more context/wrapper for the code would exemplify what you're after.
    the hardest line to type correctly is: stty erase ^H
      Thank you all !!
      My question is answered 100% !