Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Re: Is it possible to create a sub exclusive to a sub?

by FoxtrotUniform (Prior)
on Sep 19, 2004 at 00:10 UTC ( [id://392070]=note: print w/replies, xml ) Need Help??


in reply to Is it possible to create a sub exclusive to a sub?

I played around with this a while ago, but not in any great depth. As far as I can tell, it's possible to declare a sub inside another sub block, but any named subs you declare are globally accessible symbols.

If you want a truly local sub, your best bet is probably to build a closure lexically-scoped anonymous sub (thanks revdiablo):

sub foo { this; that; my $bar = sub { # ... }; # EDIT: this semi needs to be here if(cond) { $bar->(); } else { for (a loop) { something based on $_; $bar->(); } } }

It's cruftier than a local named sub, but it should do the trick.

--
F o x t r o t U n i f o r m
Found a typo in this node? /msg me
% man 3 strfry

Replies are listed 'Best First'.
Re^2: Is it possible to create a sub exclusive to a sub?
by revdiablo (Prior) on Sep 19, 2004 at 02:42 UTC
    If you want a truly local sub, your best bet is probably to build a closure

    Just a bit of clarification, a closure is not strictly necessary. What he wants is a lexically scoped, anonymous subroutine -- which is what you've demonstrated here. Whether that subroutine creates a closure is beside the point.

Re^2: Is it possible to create a sub exclusive to a sub?
by punkish (Priest) on Sep 19, 2004 at 00:18 UTC
    thanks for the reply. Looks like a neat trick, unfortunately, trying that gives me the error --
    Global symbol "$bar" requires explicit package name at...

      D'oh! My fault; the anonymous sub block needs to be delimited with a semicolon. Code changed.

      Here's a minimal example of what I think you're looking for:

      #! /usr/bin/perl -w use strict; sub foo { print "in foo\n"; my $bar = sub { print "in bar\n"; }; if(0 == @_) { $bar->(); } else { for (@_) { print "foo called with $_; "; $bar->(); } } } &foo(); &foo(qw(one two three));

      --
      F o x t r o t U n i f o r m
      Found a typo in this node? /msg me
      % man 3 strfry

        putting a semi (and correcting one of my own stupidities) results in everything running correctly. All's happy in punkish's perl land... thanks FoxtrotUniform.

      To make that work, you have to do what FoxtrotUniform did and declare and assign $bar before you use it, not afterwards as appears in the OP.

      You can, of course, declare subroutines within the block of other subroutines, but you will face two issues. One, as FoxtrotUniform mentioned, the sub is still global anyway. The other is that if the inner sub references any lexical variables declared in the outer sub, strange things will happen. Open up perldoc perldiag and look for the message "will not stay shared."

      Incidently, why do you want a sub sub? Is it so your sub can access private variables, or so your sub can use a routine name that may already be in use, or what? Just curious.
        Incidently, why do you want a sub sub? Is it so your sub can access private variables, or so your sub can use a routine name that may already be in use, or what? Just curious.

        One of the nice things about block-local sub definitions is that they stay local to that block. In other words, you only have to understand that sub in the context of the block it's declared in, which makes a lot of sense when that's the only place it gets used.

        For example, I have some C code that reads a TARGA image. Obviously, I don't want to do everything in a single function, so I break it up into one user-visible routine (read_tga_file) and two helper routines (read_tga_header and read_tga_image). The two helpers only ever get called within read_tga_file, so why should they be part of tga.o's global symbol space? If I could declare the helpers within read_tga_file's symbol space, anyone reading the file would know that they only get used there. That's a win, especially when the helper functions are a bit less obviously specialized. Lexical function declarations let you encode some of your assumptions in source code.

        This idea of "declare stuff in the smallest enclosing lexical block" is ubiquitous in the functional-programming world. As usual, Perl lets you do it with minimal fuss.

        --
        F o x t r o t U n i f o r m
        Found a typo in this node? /msg me
        % man 3 strfry

        Incidently, why do you want a sub sub?

        simply to cut down on line clutter.

        The subsub has a lot of lines that otherwise would be repeated. Now they don't have to be... I have had run into this a lot in the past, but have never figured it could be possible. Now I know a better way of doing what I have been doing.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chilling in the Monastery: (4)
As of 2024-03-28 20:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found