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

I have got a program written up and I have one scalar which I wish to pass from one file to another directly. So I had our $thingy; but the machiene I tried to run it on informed me that "Use of reserved word "our" is deprecated" so I opened up the library file and changed it to my $thingy. But now I am informed that $thingy is undefined when I run the program, its just a warning, but when $thingy is declared as an our the warning does not appear.
Furthermore, when attempting to construct a sample program to demonstrate what on earth I am talking about, I ran into a REALLY odd set of output.
program.pl #!/usr/bin/perl -w use strict; use lib '/home/httpd/cgi-bin/testing/WORTHLESS'; use library; print $library::my; print $library::our; my $thing = $library::my; my $other = $library::our; print "$thing\n$other"; -------------- library.pm my $my = "my"; our $our = "our"; print "lib $my\n$our endlib";
those are my sample programs, so why is it exactly that I get this output?
#./program.pl lib my Use of uninitialized value in print at ./program.pl line 6. Use of uninitialized value in print at ./program.pl line 7. Use of uninitialized value in concatenation (.) or string at ./program +.pl line 12. Use of uninitialized value in concatenation (.) or string at ./program +.pl line 12. our endlib
It is my understanding that the "lib my" and the "our endlib" should be printed out directly after each other given they are part of the same print statement. Obviously I am wrong.
Anyone know how to correct these errors or take a shortcut around the "Use of reserved word "our" is deprecated" problem?

jcpunk
all code is tested, and doesn't work so there :p (varient on common PM sig for my own ammusment)

Replies are listed 'Best First'.
Re: odd things with my and our
by hardburn (Abbot) on Jan 25, 2004 at 04:50 UTC

    In library.pm, you declare two scalars that are stored in very different places by Perl. our declares a variable in the symbol table, while my declares a variable in the lexical pad. When you say $library::our, you're asking for the variable declared in the library package's symbol table. Likewise, $library::my gets at the symbol table, but since $my was declared as a lexical, there is no entry for it in the symbol table, so you get undef back (strict 'vars' is meaningless when accessing the symbol table).

    Getting at the lexical pad is possible, but very difficult. This should be considered a feature.

    ----
    I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
    -- Schemer

    : () { :|:& };:

    Note: All code is untested, unless otherwise stated

      You've got a better understanding than jcpunk, but you don't have it quite right. "our" has the same scoping rules as "my" (perldoc -f our).

        our has the same scoping rules as my, but only for the name of the variable. With our, the aliased name of the variable goes away at the end of the lexical scope, but the variable itself is still there. It is still accessible from its fully-qualified name, or with another our declaration.

        Here's a quick demonstration. This fails because the name $foo has gone out of lexical scope:

        $ perl -Mstrict -le '{ our $foo = "foo"; print $foo; } print $foo' Variable "$foo" is not imported at -e line 1. Global symbol "$foo" requires explicit package name at -e line 1. Execution of -e aborted due to compilation errors.

        But this succeeds because the variable itself is still around:

        $ perl -Mstrict -le '{ our $foo = "foo"; print $foo; } print $main::fo +o' foo foo

        That said, I'm not so sure what hardburn has not got "quite right." I don't really see him mention the name scoping of either types of variables anywhere in his post.

      Getting at the lexical pad is possible, but very difficult.
      How? This looks like it could be interesting! Mind sharing? (That isn't sarcasm. I do really want to know).



      Code is (almost) always untested.
      http://www.justicepoetic.net/

        You can always trawl through /dev/kmem . . .

        PadWalker gives limited access to the pads.

        I remember there being a way to get at any pads, but I don't remember how exactly (this isn't something I do every day . . . ). It was in reference to a node on how to break lexically-declared variables for private object data. The process was so difficult that the equivilent ammount of work in any other OO language could also break object privacy. Sorry, that's all I remember.

        ----
        I wanted to explore how Perl's closures can be manipulated, and ended up creating an object system by accident.
        -- Schemer

        : () { :|:& };:

        Note: All code is untested, unless otherwise stated

Re: odd things with my and our
by jdtoronto (Prior) on Jan 25, 2004 at 05:03 UTC
    Well, here is my slightly altered version, I just put your library.pm in the same directory as the script BUT note I added the package name:
    #!/usr/bin/perl -w use strict; use library; print "Library-my: ", $library::my, "\n"; print "Library-our: ", $library::our, "\n"; my $thing = $library::my; my $other = $library::our; print "Thing: $thing\nOther: $other";
    and the package:
    package library; my $my = "my"; our $our = "our"; print "lib $my\n$our endlib \n\n";
    now the result is:
    Use of uninitialized value in print at testing.pl line 5. lib my our endlib Library-my: Library-our: our Thing: Other: our Use of uninitialized value in concatenation (.) or string at testing.pl line 11.
    Which is exactly as I would expect. The our declaration is added to the symbol table, but the my is lexically scoped within the package and thus invisible outside it. As for our being deprecated, well, perldoc for 5.8.0 does not say so. Using our effectively globalises the variable, which is generally considered poor coding style, at least the way I was taught!

    Wouldn't it be cleaner to be able to get the value programatically without the effects, possibly quite dangerous, of a global? This works and allows you to get the varaibles from within the package without the global.

    #!/usr/bin/perl -w use strict; use library; my ($lib_my, $lib_our) = library->retvals; print "Returned my : $lib_my and returned our : $lib_our\n"; #------------------------- #library.pm package library; my $my = "my"; our $our = "our"; sub retvals { $self = shift; return $my, $our; }
    jdtoronto
Re: odd things with my and our
by blokhead (Monsignor) on Jan 25, 2004 at 04:47 UTC
    print "lib $my\n$our endlib";
    Your output is unbuffered, and since there's no \n at the end of this line, it gets caught in the STDOUT buffer until the program exits. In the meanwhile, warn prints its thing to STDERR (whose buffer gets flushed after each warning because of the newlines). Put a newline at the end of this print (or unbuffer STDOUT with $|=1) and you'll get output you expect.

    As for the global vars across files, you should use use vars to declare the variable instead of our. In your test, the our declaration binds $lib::our only for the library.pm file (more specifically, it binds it only for the lexical scope of that our). Using use vars is not only more portable for older perls that don't support our, but it is truly global. And I don't understand at all trying to use my to achieve this, as it doesn't use the symbol table (ie, $lib::var vars).

    Update: I was a little off here.. As jdtoronto points out below, you can still declare our variables to be global across files. our makes it so you can call a package variable by its short name ($foo) within the lexical scope. Outside that scope you can still get to it by its fully-qualified name ($lib::foo) as you do in your main code. But anyway, using use vars will make this work with older perls like you need, and get rid of your "deprecated" warnings.

    package lib; use vars '$usevars'; $usevars = "foo"; ## now $lib::usevars is visible, even from other files

    There's a lot of good reference material in the Functions, Subroutines, and Variables section of Tutorials about these three different types of variable declarations.

    Update: added use vars snippet.

    blokhead

Re: odd things with my and our
by Coruscate (Sexton) on Jan 25, 2004 at 05:30 UTC

    As for the error you are receiving about the use of our(), I'm going to assume you are using an older version of perl in which our() was not yet introduced (or else an extremely new version where our() has suddenly become deprecated (which I highly doubt)). Though I wonder why the error message includes the part about deprecation. Wouldn't/shouldn't it just complain about a reserved word and not about deprecation? Just going by the English language, in which 'deprecated' means that the behaviour is being phased out, being replaced by a newer behaviour.

      I am using an old version of perl (which i cannot avoid) but the part about deprecation made me think that the sysadmin finally upgraded it without my knowlege to some weird perl6 beta or something odd like that, but with some proding (I dont have shell access to the machiene, just ftp) I was able to coax this out of it
      This is perl, version 5.005_03 built for i386-linux
      Copyright 1987-1999, Larry Wall

      Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5.0 source kit.

      Complete documentation for Perl, including FAQ lists, should be found on this system using `man perl' or `perldoc perl'. If you have access to the Internet, point your browser at http://www.perl.com/, the Perl Home Page.

      So that is indeed odd and looks like use vars and I are going to have to get aquanted.

      sadly this computer just landed itself under my dominion and it is a bit different on that version of perl.
      thanks for the help.


      jcpunk
      all code is tested, and doesn't work so there :p (varient on common PM sig for my own ammusment)
Re: odd things with my and our
by bart (Canon) on Jan 25, 2004 at 15:15 UTC
    The complaint about our leads me to believe you have a perl that is quite old, so old that it doesn't support our, but not too old so it doesn't know about it. What is it, 5.005_x?

    A quick fix, even for older perls, is to replace our $var; with use vars qw($var);. You must take care that the variables in both files are in the same package, or else, simply use fully qualified variables (= including the package name, like $Foo::var) — that way, you don't have to declare them.

    Or you could import/export them.