Hi,

I was just tidying up an old mod_perl script which had some ugly "use
vars qw(...);" lines in it which I thought I'd replace with "our ...;".
I realise this isn't always a good idea since "our" is not intended as a
replacement for "use vars", but its often OK and I thought it would be
in my case.

I was only half right:  The script still works fine, but emits warnings
which it previously didn't about "variable will not stay shared".

The mod_perl Guide (1.28) refers to such problems in section 3.5:

It gives as an example the following program:

    use strict;
    use warnings;

    sub print_power_of_2 {
        my $x = shift;
        sub power_of_2 {
             return $x ** 2;
        }
        my $result = power_of_2();
        print "$x^2 = $result\n";
    }

    print_power_of_2(5);
    print_power_of_2(6);

This prints:

    Variable "$x" will not stay shared at ./nested.pl line 7.
    5^2 = 25
    6^2 = 25

The solution is to use a package-global $x which won't get deep-bound
into power_of_2():

    use strict;
    use warnings;

    sub print_power_of_2 {
        use vars qw($x);
        $x = shift;
        sub power_of_2 {
             return $x ** 2;
        }
        my $result = power_of_2();
        print "$x^2 = $result\n";
    }

    print_power_of_2(5);
    print_power_of_2(6);

This prints:

    5^2 = 25
    6^2 = 36

However, if you change the ugly "use vars" to the
sexier-although-not-quite-the-same "our":

    use strict;
    use warnings;

    sub print_power_of_2 {
        our $x = shift;
        sub power_of_2 {
             return $x ** 2;
        }
        my $result = power_of_2();
        print "$x^2 = $result\n";
    }

    print_power_of_2(5);
    print_power_of_2(6);

then it prints:

    Variable "$x" will not stay shared at ./nested.pl line 7.
    5^2 = 25
    6^2 = 36

!!!

In other words, we get a bizarre cross between the two: the warning
about $x not staying shared is emitted, but of course its nonsense (?)
because package-globals don't get deep-bound into subroutines anyway,
and the program actually works fine!

The eagle-eyed will have noticed that the above "use vars" solution is
not *exactly* as presented in the mod_perl Guide:  the solution there
puts the "use vars" *outside" of the declaration of print_power_of_2(),
not *inside* as above.  This, of course, makes no difference to "use
vars" which affects the package, not a lexical scope.

But it *does* make a big difference to "our", which applies to a lexical
scope, not a package:  If we move the "our" *outside* of the declaration
of print_power_of_2():

    use strict;
    use warnings;

    our $x;

    sub print_power_of_2 {
        $x = shift;
        sub power_of_2 {
             return $x ** 2;
        }
        my $result = power_of_2();
        print "$x^2 = $result\n";
    }

    print_power_of_2(5);
    print_power_of_2(6);

then the confusing warning goes away:

    5^2 = 25
    6^2 = 36

Why am I bringing this up?

(a) because I think the mod_perl Guide needs to mention the use of "our"
as well as "use vars" (they're only very briefly mentioned, regarding
something else, in section 10.6.5);
(b) because I can't actually do what I just did above in my mod_perl
script!

I run my mod_perl script under Apache::Registry, which (as we all know)
makes the script into a subroutine, and therefore any subroutines into
inner subroutines.

In the example above, print_power_of_2() is like my script, power_of_2()
is like a subroutine in my script, and the two calls to
print_power_of_2() are like my script being run twice.

Obviously I can't move the "our" declaration *outside* my script like I
did above (unless Apache::Registry did this for me when it does its
stuff with my script), so I'm stuck with the warning (or else "use
vars").

Is there some reason why the warning gets emitted with "our" inside
print_power_of_2()?  Was I just lucky that this particular example
worked and I should really heed the warning, or is the warning actually
bogus?

Is there any way I can use "our" rather than "use vars" and not get
these warnings?

- Steve Hay


Reply via email to