Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
PerlMonks  

my sub ?

by bcrowell (Acolyte)
on Mar 25, 2002 at 19:47 UTC ( #154190=perlquestion: print w/ replies, xml ) Need Help??
bcrowell has asked for the wisdom of the Perl Monks concerning the following question:

Is there any way to do the equivalent of
my sub foo {}
?

In other words, I want a subroutine within a subroutine that is invisible to every other subroutine in the same package. Specifically, I have a one-line helper routine that I'd like to have with the same name within many parent subroutines, using slight variations in each one. But if I do

sub a { sub x {} } sub b { sub x {} }
then the second x()'s definition overrides the first one's.

Is the best way to do this by just having a subroutine reference at the package level, and assigning anonymous subroutines into it from inside a() and b()?

Comment on my sub ?
Select or Download Code
Re: my sub ?
by shotgunefx (Parson) on Mar 25, 2002 at 19:51 UTC
    Yes. You can use an anonymous subroutine.
    sub a { my $xcode= sub { print "Hidden!\n"; }; $xcode->(); }

    But "Is the best way to do this by just having a subroutine reference at the package level, and assigning anonymous subroutines into it from inside a() and b()?" sounds like a method which means you should probably be looking into using objects.

    -Lee

    "To be civilized is to deny one's nature."
Re: my sub ?
by chromatic (Archbishop) on Mar 25, 2002 at 19:53 UTC
    Use anonymous subroutines.
    my $sub = sub { # do something };
    It doesn't work to declare "inner" subroutines because all subroutine names are visible at the package level.
Re: my sub ?
by maverick (Curate) on Mar 25, 2002 at 19:57 UTC
    You could make anonymous subrouting references to (x) in sub a & b like so:
    sub a { my $ref = sub { print "x1\n"; }; &$ref; } sub b { my $ref = sub { print "x2\n"; }; &$ref; } &a; &b;
    The only thing that will look different is the call to the fucntion if you can live with that.

    /\/\averick
    perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

      Doesn't calling a sub reference with & imply the passing of your @_ ?

      -Lee

      "To be civilized is to deny one's nature."
        Yes it does, but if you just stick $ref; out there by itself, or with () after it, perl doesn't get that that's supposed to be a function call and throws a syntax error.

        You pretty much have to have the & as far as I know.

        Or you could use $ref->(); It's monday and I'm being a blonde.

        Update:Thanks chromatic, Fletch, and shotgunefx for the clue-by-four-ing.

        /\/\averick
        perl -l -e "eval pack('h*','072796e6470272f2c5f2c5166756279636b672');"

Re: my sub ?
by broquaint (Abbot) on Mar 25, 2002 at 20:02 UTC
    If you define a sub within a sub it unfortunately gets imported into the the current package's symbol table. A possible solution would be
    use strict; sub x { print "x() in main::\n"; } sub a { local *x = sub { print "x() in a()\n"; }; x(); } sub b { local *x = sub { print "x() in b()\n"; }; x(); } &a(); &b(); &x();
    But this assumes that *x is declared within the same package as a() and b().
    HTH

    broquaint

    update [2002-05-20]: you could also check out the beginnings of a small module that attempts to give the illusion of having lexically scoped subs.

Re: my sub ?
by Anonymous Monk on Mar 25, 2002 at 20:35 UTC
    Thanks, all, for the help! Much appreciated! I don't know if I've ever run across an online community that welcomes newbies as warmly as this one.

    It seems that, as always, there's more than one way to do it.

    The suggestion about using local typeglobs got me thinking that really what I want to do can be done more cleanly like this: Define the helper subroutine x() once at the outside level. Have a variable that modifies its behavior appropriately, and let that variable be declared as local within each subroutine that's going to call the helper.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (7)
As of 2014-09-20 10:03 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (158 votes), past polls