Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

why use a coderef?

by juanbro (Acolyte)
on Jun 25, 2007 at 12:37 UTC ( #623162=perlquestion: print w/ replies, xml ) Need Help??
juanbro has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking at some code that essentially says:
my $coderef = \&some_subroutine; my ($foo,$bar) = &$coderef('arg1'); my ($biz,$baz) = &$coderef('arg2'); my ($ying,$yang) = &$coderef('arg3'); sub some_subroutine { #...do something with @_... return ($value1, $value2); }
Why would one use a coderef here? Why not just say:
my ($foo,$bar) = some_subroutine('arg1');
Thanks

Comment on why use a coderef?
Select or Download Code
Re: why use a coderef?
by clinton (Priest) on Jun 25, 2007 at 12:43 UTC
    From the code you have presented here, there is no apparent reason. Have you not perhaps taken it out of context?

    Clint

Re: why use a coderef?
by Limbic~Region (Chancellor) on Jun 25, 2007 at 12:57 UTC
    juanbro,
    There are a number of reasons why one might use a code ref. You may be dynamically constructing the routine which is not the case here. You may be using something like File::Find where a routine in user land must be called in the module's scope. That is also not the case here. I could go on with reasons why one might do this but out of context, I have no idea.

    Cheers - L~R

Re: why use a coderef?
by exussum0 (Vicar) on Jun 25, 2007 at 13:29 UTC
    Technically, you don't /have/ to. It's a construct of convenience for someone. All one ever really needs to code is a way of doing addition and subtraction, jumping to a particular place in code and some hardware interface.

    The code ref allows you to pass around what you'd want to jump to, not all that different from array indexes if you step back a little. Code refs are just values passed around to say what should be executed next. Array indexes are just values that can be recalled to know which value you meant, later.

    If they seem nasty, you could always pass around labels you can goto, to. :)

Re: why use a coderef?
by whereiskurt (Friar) on Jun 25, 2007 at 13:58 UTC

    superdoc:

    Could it be that when you call 'some_subroutine()' with a certain parameter it alters the globally scoped variable '$coderef'? IF 'some_subroutine' looked like this:

    sub some_subroutine { if ($_[0] eq 'arg1') { $coderef = \&some_other_subroutine; } return ($value1, $value2); }

    The second calls to '$coderef' with 'arg2/3' will call '&some_other_subroutine'. This is the nature of the coderef -- my logic is wired to the '$codref' and the executing code can change where that reference points to.

    I suppose this could be 'the basics' of it, but if you're looking for *deeper* insight, I'm sure we could provide some of that too... :-)

    Kurt

Re: why use a coderef?
by ikegami (Pope) on Jun 25, 2007 at 14:29 UTC

    The usual reason is to provide flexibility to allow code reuse.

    For example, consider sort. Specify a coderef allows us to use sort to sort by any criteria. Without the coderef, we'd have to have one function to sort lexically, another to sort numerically, etc. It saves us from writing many similar functions.

Re: why use a coderef?
by ferreira (Chaplain) on Jun 25, 2007 at 20:25 UTC

    There are some subtle differences:

    1. Unless the declaration of some_subroutine was moved up, there would be a warning about an undefined subroutine. The assignment runs after the declaration (which happens on compile-time) and so no warning.
    2. if the code were using anonymous subroutines as in
      my $coderef = sub { #...do something with @_... return ($value1, $value2); };
      there would be no entry on the current package/namespace/stash. That makes a really private code.
Re: why use a coderef?
by cLive ;-) (Parson) on Jun 25, 2007 at 22:11 UTC

    All good responses so far. I'll agree, in this example, I can't see a reason though.

    Just to add, another useful instance is if you want to avoid a long nested "if/else" structure, eg, instead of:

    if ($var eq 'one') { &subOne; } elsif ($var eq 'two') { &subTwo; } ... elsif ($var eq 'ten') { &subTen; } else { die "Invalid \$var"; }
    use this instead
    my %subs = ( one => \&subOne, two => \&subTwo, ... ten => \&subTen, ); if ( exists $subs{$var} ) { &{$subs{$var}}; } else { die "Invalid \$var"; }
Re: why use a coderef?
by FunkyMonk (Canon) on Jun 25, 2007 at 22:40 UTC
    Nobody else has mentioned this, so I will

    Private subroutines

    In Pascal (sorry!) you can declare a sub within another sub. In Perl you can't. But you can define & use private subrefs:

    sub my_realy_complicated_thing { my $easy_thing = sub { ... }; my $easier_thing = sub { ... }; ... my $x = $easy_thing->( @lots_of_complicated_stuff ); #etc }

    Footnote
    As I was typing this, I ended a sentence with ";"
    Am I doing too much Perl?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (12)
As of 2014-10-22 16:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (119 votes), past polls