Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

scoping across parent/child relationship

by geektron (Curate)
on Aug 30, 2001 at 20:56 UTC ( #109130=perlquestion: print w/replies, xml ) Need Help??

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

I don't understand why I'm getting "Global symbol requires explicit package" errors for some variables I'm using only in a child process. Here's a code snippet.

if ( $pid = fork ) { ## parent process ## do parent stuff } else { ## child process my ( $foo, %bar, $bax ); Initialize_child(); do_child_stuff(); }
the variables declared in the child process are only used in sub Initialize and in sub do_child_stuff, so I would think that the scope is valid...

if I declare the variables earlier ( say, just before the fork ), there isn't a problem...

can anyone shed some light for me?

Replies are listed 'Best First'.
Re: scoping across parent/child relationship
by rchiav (Deacon) on Aug 30, 2001 at 21:17 UTC
    my ( $foo, %bar, $bax ); is scoped within the else. It doesn't look like Initialize_child exists within that scope. I think there are two options, of which I think only one would be recomended.

    1) pass the variables to the sub (recomended)
    2) create the sub within the else block (not recomended).

    Just to further explain, here's some example code that will give you the same results.

    # $foo and $bar are not accessable outside of this scope { my ($foo, $bar) = qw(Hello world); DoSomething(); } # this is outside of the above scope so it can not access $foo and $ba +r sub DoSomething { print "$foo $bar\n"; }
    Or if it existed inside the scope (not recomended, just for demonstrative purposes)
    # $foo and $bar are not accessable outside of this scope { my ($foo, $bar) = qw(Hello world); DoSomething(); # this is inside the scope so it can access $foo and $bar sub DoSomething { print "$foo $bar\n"; } }
    Hope this helps
    Rich
Re: scoping across parent/child relationship
by Hofmator (Curate) on Aug 30, 2001 at 21:23 UTC

    I suspect your error is not related to the forking in any way. From your question I'm guessing that your subs look sth like this

    sub Initialize_child { print $foo; }
    but they are declared outside somewhere else in your program. But this code doesn't work. Let's simplify
    use strict; my $foo = 1; bar(); sub bar { print $foo; }
    This code works, because the declaration of the sub is in the same scope as the my. Now let's change this:
    use strict; { my $foo = 1; bar(); } sub bar { print $foo; }
    This doesn't work any longer because variables declared with my are not visible in subroutines called from the same scope unless the subroutine is declared in this scope as well (see example above).

    If this isn't your problem, post some more code.

    -- Hofmator

      This doesn't work any longer because variables declared with my are not visible in subroutines called from the same scope unless the subroutine is declared in this scope as well (see example above).

      this is the issue. i wasn't thinking it through, and obsessing on the forking, not on the scoping.

Re: scoping across parent/child relationship
by VSarkiss (Monsignor) on Aug 30, 2001 at 21:21 UTC

    The code actually looks OK, but be aware that parent/child relationships and lexical scoping (the kind you're getting with my) are very different things. You may find it helpful to read MJD's excellent document Coping with Scoping or Variable Scoping in Perl: the basics (which actually gets into fairly advanced stuff).

    Wild guess: are you trying to use the variables declared in the else horn elsewhere in the program?

Re: scoping across parent/child relationship
by herveus (Parson) on Aug 30, 2001 at 21:23 UTC
    Howdy!

    You misunderstand scope and my and all that. Pray consider my explanation.

    When you write:

    else { my ($foo, %bar, $bax); ... }
    $foo, %bar, and $bax are only visible within those braces.

    Initialize_child and do_child_stuff are presumable defined elsewhere (not within those braces). When they refer to $foo, etc., they are referring to global variables, hence the warning that you get (good on you for using 'use strict').

    If you want those variables to be visible to those subs but nowhere else, do something like:

    { my ($foo, %bar, $bax); sub Initialize_child { # code here } sub do_child_stuff { # more code here } }

    yours,
    Michael

Re: scoping across parent/child relationship
by demerphq (Chancellor) on Aug 30, 2001 at 22:49 UTC
    geektron: the variables declared in the child process are only used in sub Initialize and in sub do_child_stuff, so I would think that the scope is valid... Nope. Other people have explained why so I wont comment. But I was wondering why you dont pass them as parameters to the functions? Then scoping doesnt become a problem:
    my ( $foo, %bar, $bax ); Initialize_child($foo,\%bar,$bax); do_child_stuff($foo,\%bar,$bax);
    or with named parameters:
    sub Init_Child { my %params=@_; #blah } Init_Child(name=>$foo,attribs=>\%bar);

    Yves
    --
    You are not ready to use symrefs unless you already know why they are bad. --tadmc (CLPM)
      But I was wondering why you dont pass them as parameters to the functions? Then scoping doesnt become a problem

      because i need them in both subs, and the actual variables are ( rather large ) config hashes. they can be global to the child ( if that makes sense )....

      just trying to get the most out of laziness...

        Sorry but thats not a good reason. Pass them by reference, or in a hash, or even create an object that bundles them all together into a nice package.
        Globals vars are evil without very very good justification. There is almost always an easier and safer way to do things.
        Almost the only time I use them is for things like a $Debug variable in a package.

        OTOH, its your code.... :-)

        Yves
        --
        You are not ready to use symrefs unless you already know why they are bad. -- tadmc (CLPM)
        Then why not pass them as ref's?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others pondering the Monastery: (5)
As of 2021-10-20 17:13 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    My first memorable Perl project was:







    Results (81 votes). Check out past polls.

    Notices?