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
| [reply] [d/l] [select] |
|
|
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).
| [reply] |
|
|
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. | [reply] [d/l] [select] |
|
|
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).
| [reply] |
|
|
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
| [reply] [d/l] [select] |
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 | [reply] [d/l] [select] |
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.
| [reply] [d/l] [select] |
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.
| [reply] |
|
|
| [reply] |
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. | [reply] [d/l] [select] |