Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

providing a callback routine to sort

by Anonymous Monk
on Jan 21, 2014 at 20:51 UTC ( #1071519=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks, Is this possible? I have an object with a myList element. I would like to provide a client who uses the object the ability to use their own sorting routine. If they don't provide one, it fall backs to an internal sort routine. When I try to run my script, however, the fallback works as expected, but the $a and $b internal variables are undefined (they are not elements of $myList) in the client callback. Am I doing something wrong here or is this not possible? Thanks in advance.
##Object: sub _byCode { $a->asStringFmt() cmp $b->asStringFmt; } my $callback = $self->{sortCallback} || "_byCode"; ... foreach my $key (sort $callback @{$myList->getKeys}) { ... }
##Client: my $byCodeAndX = sub { .... }; my $obj = new Obj( sortCallback => $byCodeAndX )

Replies are listed 'Best First'.
Re: providing a callback routine to sort ( $::a $::b )
by Anonymous Monk on Jan 21, 2014 at 21:53 UTC

    Well, ... isn't sufficient for reproducing

    Anyway the error message I get is Use of uninitialized value $Foo::a in numeric comparison (<=>) at - line 2.

    $Foo::a is not the same as $main::a aka $::a aka perlvar#$a
Re: providing a callback routine to sort
by pemungkah (Priest) on Jan 21, 2014 at 22:04 UTC
    Just did this the other day. The key is to remember that sort's curly block is essentially an anonymous sub, so what you put there has to be executable code. In the case of a sort subroutine, this means you need to do something like this:
    my $dir = shift; my $sort_sub = $dir eq 'up' ? sub {$a <=> $b} : sub {$b <=> $a}; my @items = (3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5); print "@{[sort { $sort_sub->() } @items]}\n";
    Which gives us
    $ perl sample up 1 1 2 3 3 4 5 5 5 6 9 $ perl sample down 9 6 5 5 5 4 3 3 2 1 1
    Note that the code in the sort curlies calls the callback itself.
        So it is - thanks! I'm just so used to having the curlies in there that I'd forgotten I could drop them.
Re: providing a callback routine to sort
by Anonymous Monk on Jan 21, 2014 at 23:01 UTC
    In Perl, "a reference" can be a reference to anything, including a subroutine (ref($whatever) eq 'CODE' ...) So, you certainly could provide sort with a subroutine that checks if $whatever refers to a subroutine, and if so, calls it ... otherwise taking some default action. . .

    Notice how the sort routine, within your code, has only one clear subroutine to call. That subroutine, however, is faced with a decision.
Re: providing a callback routine to sort
by Laurent_R (Canon) on Jan 21, 2014 at 23:26 UTC
    I really think you did not provide enough information to help you, but this:
    $a->asStringFmt() cmp $b->asStringFmt;
    looks probably wrong to me. Left side looks like a function, right side not.

      I really think you did not provide enough information to help you

      See Re: providing a callback routine to sort ( $::a $::b )

      The only reason $a and $b are undefined is because they're not $main::a and $main::b -- sort deals with $main::a and $main::b or $::a for sort -- this is the OPs problem and the solution, use the right variable (package affects unqualified variables)

      sort talks about this exactly

      An alternate solution (using prototypes) is also talked about in sort and in chromatics free book Modern Perl a loose description of how experienced and effective Perl 5 programmers work....You can learn this too.

      looks probably wrong to me. Left side looks like a function, right side not.

      Well, they're both perfectly identical method calls

        Thank you! I provided $pkgdir::pkg::a and $pkgdir::pkg::b and it worked! My apologies for missing that in the documentation. Unfortunately, it's all the way at end (in very tiny letters ;)

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1071519]
Approved by hdb
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (2)
As of 2022-07-01 08:18 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My most frequent journeys are powered by:









    Results (98 votes). Check out past polls.

    Notices?