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

Hello Perl Monks,

I have a very basic question about print statements. I am looking for a bug in my program. I think I found it, and I'm using print statements to help me out. So, say I have this global variable $variable. I also have a local variable by the same name within the subroutine &subroutine. If I add in a print statement within &subroutine asking perl to print $variable, will it print the global variable $variable or the local variable $variable? If it prints the value of the global variable, how would I get Perl to print the value of the local variable? Any advice would solve all my life problems,

Molly

Replies are listed 'Best First'.
Re: Basic Print statement question
by FunkyMonk (Bishop) on Jul 23, 2007 at 18:36 UTC
    This is the program I came up with from your description (I hope it's what you meant). Problems are often better described with code, rather than English.
    use strict; use warnings; my $variable = 1; print $variable; subroutine(); sub subroutine { my $variable = 2; print $variable; } #Output: #12

    Each print prints the value of the $variable it's closest to (in this example only, it's not a rule).

    I fairly sure you will benefit from reading Coping with Scoping. It'll help you understand Perl's notion of global and local variables.

Re: Basic Print statement question
by mr_mischief (Monsignor) on Jul 23, 2007 at 19:18 UTC
    It depends on what scope the print statement falls into. Consider:
    $foo = 'foo'; sub foo { print $foo . "\n"; my $foo = 'bar'; print $foo . "\n"; } foo;
    which outputs:
    foo bar
    Never do that in real code if you can help it.

    Here, the scope of the global $foo is everywhere it's not masked by another variable with that name. Within the subroutine, it is only masked from the point the lexical $foo is declared until the end of the block. The sub has two different values for two different variables with the same name. That's a mess, and would be better avoided than implemented correctly. Implementing it correctly with the two variables named the same is just asking for someone to move the declaration of the lexical or the use of the global, and then you've got broken code.

    You might not be able to control the naming of the global, but one would hope that you can control the name of the lexical. I would carefully name it something different.
Re: Basic Print statement question
by Argel (Prior) on Jul 23, 2007 at 22:20 UTC
    Did you have something like this in mind?
    #!/usr/bin/perl use strict; use warnings; our $var = 'foo'; sub test { my $var = 'bar'; print $main::var, "\n"; print "$var\n"; } test();

    Output:

    foo bar

    Notes:

    1. You really shouldn't reuse variable names like this. As you have already discovered it makes debugging a lot more difficult and increases the likelihood of making mistakes.
    2. You should read up on 'our' to understand the full ramifications of using it (e.g. run perldoc -f our).
Re: Basic Print statement question
by andreas1234567 (Vicar) on Jul 23, 2007 at 19:49 UTC
Re: Basic Print statement question
by ysth (Canon) on Jul 23, 2007 at 20:29 UTC
    Depends on what you mean by "global" and "local", since perl doesn't really have those categories. Perl does have lexical (declared with "my" and, in 5.10, "state") and package (declared with "our", "use vars", or "local") variables. Package variables are sometimes called "global" variables, but file-scoped lexical variables sometimes are too. I don't know which you mean.

    For variables of the same name, whichever was most recently declared in the lexical scope will be what's used, whether by print or anything else, when you just say $variable. (Where "declared" means via "my", "state", or "our".)

    You can explicitly get a package variable by qualifying with the package name it was declared in, where the default package is "main" (with the empty string as an alias). So $main::var (aka $::var) will get the package variable, even if $var is a lexical at that point in your code.

    I hope this helps you at least enough to rephrase your question.