my variable is recognized in following sub

T

Tad J McClellan

Within the package where this is declared, all is fine if I use the package name.


Outside of the package, all is ALSO fine if you use the package name!

(this is why you should alway prefer lexical variables over package
variables, except when you can't. i.e. package variables open you
up to "action at a distance" type of bugs.
)

Here is cut & paste code sample:


Thank you.

---------------------------------------
package FunStuff;

use strict;

our $IwannaBeApackageGlobal = "use strict then";
$FunStuff::IwannaBeApackageGlobal3 = "use strict then = 3";

print $IwannaBeApackageGlobal,"\n"; # works with strict


Works because it was declared with our().

print $FunStuff::IwannaBeApackageGlobal3,"\n"; # works with strict


Works because it uses the fully qualified name.

print $IwannaBeApackageGlobal3,"\n"; # does not work with strict

----------------------------------------------------------------------------------
Error: Variable "$IwannaBeApackageGlobal3" is not imported at [...] line 10.


Why do I get this error when printing $FunStuff::IwannaBeApackageGlobal3 as just
$IwannaBeApackageGlobal3.


Because that is what "strict vars" is supposed to do.

That is, $IwannaBeApackageGlobal3

was not declared via "our" or "use vars"
and
was not localized via "my()"
and
was not fully qualified


perldoc strict

...
"strict vars"
This generates a compileâ€time error if you access a variable that
wasn’t declared via "our" or "use vars", localized via "my()", or
wasn’t fully qualified.
 
D

david

Hi all,

I wanted to share my findings about my variables and following sub.

The following program works:

use strict;
use warnings;

my $a = 30;
foo();

sub foo {
print $a,"\n",
}

It prints 30 as output. At the first glance it was suprising for me
how the $a variable is recognized by the sub. They are really in the
same scope. If this is intended by the user (closures) this is
wonderful but it can cause bugs.
The only solution is to write the function at the beginning.

use strict;
use warnings;

sub foo {
print $a,"\n",
}

my $a = 30;
foo();

This won't compile

Hope this will save from other programmers to get unexpected errors.

Have a nice and productive day,
David
 
J

John W. Krahn

david said:
I wanted to share my findings about my variables and following sub.

The following program works:

use strict;
use warnings;

my $a = 30;
foo();

sub foo {
print $a,"\n",
}

It prints 30 as output. At the first glance it was suprising for me
how the $a variable is recognized by the sub. They are really in the
same scope. If this is intended by the user (closures) this is
wonderful but it can cause bugs.

That is not a closure.

perldoc -q closure

The only solution is to write the function at the beginning.

use strict;
use warnings;

sub foo {
print $a,"\n",
}

my $a = 30;
foo();

This won't compile

It *will* compile. It will also warn about the use of $main::a and with
warnings disabled it won't even do that.

$ perl -ce'
use strict;
use warnings;

sub foo {
print $a,"\n",
}

my $a = 30;
foo();
'
Name "main::a" used only once: possible typo at -e line 6.
-e syntax OK




John
 
S

Scott Bryce

david said:
Hi all,

I wanted to share my findings about my variables and following sub.

The following program works:

use strict;
use warnings;

my $a = 30;
foo();

sub foo {
print $a,"\n",
}

It prints 30 as output.

As it should.
At the first glance it was suprising for me
how the $a variable is recognized by the sub.

Why? You declared $a as a global variable.
They are really in the
same scope. If this is intended by the user (closures) this is
wonderful but it can cause bugs.

Which is why you should declare variables in the smallest possible scope.
The only solution is to write the function at the beginning.

Or don't declare variables in a broader scope than necessary.
 
D

david

As it should.


Why? You declared $a as a global variable.


Which is why you should declare variables in the smallest possible scope.

why is $a a global variable? if i write my $a it does not make it to a
local variable?
 
S

Scott Bryce

david wrote:
why is $a a global variable? if i write my $a it does not make it to
a local variable?

Since $a was declared outside of any block, its scope is from the place
it was declared to the end of the script. That includes the foo subroutine.

There is a sense in which $a is local, but it is local to the entire
script, starting from the place where it was declared.

http://perl.plover.com/FAQs/Namespaces.html
 
S

sln

Hi all,

I wanted to share my findings about my variables and following sub.

The following program works:

use strict;
use warnings;

my $a = 30;
foo();

sub foo {
print $a,"\n",
}

It prints 30 as output. At the first glance it was suprising for me
how the $a variable is recognized by the sub. They are really in the
same scope.

Your program has its own namespace. I think its brought into the Main:: namespace.
The above works because it is really this:

{
use strict;
use warnings;
my $A = 30;
print $A,"\n";
}
If this is intended by the user (closures) this is
wonderful but it can cause bugs.
The only solution is to write the function at the beginning.

use strict;
use warnings;

sub foo {
print $a,"\n",
}

my $a = 30;
foo();

This won't compile

The above doesen't work because its really this:

{
use strict;
use warnings;
print $A,"\n";
my $A = 30;
}
__END__
Global symbol "$A" requires explicit package name at jjj.pl line 4.
 
J

Jürgen Exner

david said:
I wanted to share my findings about my variables and following sub.

The following program works:

use strict;
use warnings;

my $a = 30;
foo();

sub foo {
print $a,"\n",
}

It prints 30 as output. At the first glance it was suprising for me
how the $a variable is recognized by the sub.

Why wouldn't it be recognized? It's a normal global variable.
They are really in the same scope.

The function definition and the variable are (not that this would matter
much), but not the _body_ of the function and the global variable. The
body may define local objects, too, which will be visible in addition to
any global objects.. This is the typical semantic for the vast majority
of programming languages, nothing special about it..
If this is intended by the user (closures) this is

It is not a closure! Quite the opposite, actually.
wonderful but it can cause bugs.

Yes, of course. That is why global variables are discouraged and should
be used only when there is a good reason for using them. Again, that
applies to the vast majority of programming languages.
The only solution is to write the function at the beginning.

No!!!
First of all it doesn't work because in Perl with strictures enabled you
need to declare a variable before using it ($a is an exception, see
below).
And second it is standard best practice in any programming language to
avoid global variables unless you have a very good reason why you need
them.
use strict;
use warnings;

sub foo {
print $a,"\n",
}

my $a = 30;
foo();

This won't compile

It does compile and it even runs. All you get is a warning (if warnings
are enabled as they should be)
Use of uninitialized value in print at [...]

However using $a in Perl is not a good idea to begin with. $a and $b are
special in sort() and therefore excempt from several checks in
warnings/strict.
Had you used a different variable e.g. $x, then you would have gotten
the error
Global symbol "$x" requires explicit package name at [...]
Execution of [...] aborted due to compilation errors.
from strict, which is telling you that you are using a variable before
it is declared. This is much more to the point and more important the
reason why your "solution" doesn't work.
Hope this will save from other programmers to get unexpected errors.

Hmmm, well, except your 'solution' doesn't address the underlying
problem, violates proven best practices, and doesn't work.

jue
 
X

xhoster

Scott Bryce said:
As it should.


Why? You declared $a as a global variable.

Aren't global variables the same thing as package variables?
And aren't those mutually exclusive with lexical variables?

The scope of the lexical variable may be broad, but that doesn't
make it global, at least not in Perl vernacular as I understand it.


Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
X

xhoster

John W. Krahn said:
That is not a closure.

perldoc -q closure

Actually, I think it is a closure. It is a nasty accidental closure with
possibly undesirable consequences, for example it only closes once, at
compile time (The ability to re-close may be desirable, but by my
understanding it is not a mandatory part of the definition of a closure.
Obviously this gets into semantics, but sometimes semantics are important).

Understandably, the part of the docs that describes closures described the
*right* way to do them, not that nasty accidental way.

Xho

--
-------------------- http://NewsReader.Com/ --------------------
The costs of publication of this article were defrayed in part by the
payment of page charges. This article must therefore be hereby marked
advertisement in accordance with 18 U.S.C. Section 1734 solely to indicate
this fact.
 
T

Tad J McClellan

Your program has its own namespace.


and it is named main::

I think its brought into the Main:: namespace.


You are incorrect. Twice.

If it was a package variable, then it would be in the main:: package.

But it is a lexical variable, and lexical variables are not in any package.
 
U

Uri Guttman

x> Aren't global variables the same thing as package variables?
x> And aren't those mutually exclusive with lexical variables?

x> The scope of the lexical variable may be broad, but that doesn't
x> make it global, at least not in Perl vernacular as I understand it.

i have been watching this thread with bemusement and seeing the group
miscommunicate about this topic. let me try to clear up the mess. :)

if you declare a lexical (my) variable in the body of a perl source file
outside of any sub or block, it is best called a file scoped lexical. it
is visible from the point (or just after :) of the declaration to the
end of the file. you can even declare another my variable of the same
name and it will now be scoped to the end of the file (but it will
generate a warning so don't do it). these types of variable are also
called file globals as they are usually global to the entire file (even
though the declararation is lexical.

what most perl uses of global mean are what is more properly called
package globals. this means they are in the symbol table and truly
global to the entire program (as long as you know where to find it in
the symbol table, you can mung it at a distance).

so we have the lexically declared file scoped 'globals' and
program/package 'globals'. please note the difference now and when you
discuss these in the future. i won't even bring up 'our' which just adds
to the confusion by being a lexical declaration of a package global!

uri
 
S

sln

x> Aren't global variables the same thing as package variables?
x> And aren't those mutually exclusive with lexical variables?

x> The scope of the lexical variable may be broad, but that doesn't
x> make it global, at least not in Perl vernacular as I understand it.

i have been watching this thread with bemusement and seeing the group
miscommunicate about this topic. let me try to clear up the mess. :)

if you declare a lexical (my) variable in the body of a perl source file
outside of any sub or block, it is best called a file scoped lexical. it
is visible from the point (or just after :) of the declaration to the
end of the file. you can even declare another my variable of the same
name and it will now be scoped to the end of the file (but it will
generate a warning so don't do it). these types of variable are also
called file globals as they are usually global to the entire file (even
though the declararation is lexical.

what most perl uses of global mean are what is more properly called
package globals. this means they are in the symbol table and truly
global to the entire program (as long as you know where to find it in
the symbol table, you can mung it at a distance).

so we have the lexically declared file scoped 'globals' and
program/package 'globals'. please note the difference now and when you
discuss these in the future. i won't even bring up 'our' which just adds
to the confusion by being a lexical declaration of a package global!

uri

I agree with everything you said. 'File scoped globals', ie lexical's
in the outer scope. I'm not sure package globals are available for
access throughout the program without explicetly including the namespace
hash key, unless its imported (aliased) withing a use statement.
At least that's what I get out of the docs. I'm probably wrong, dunno.

Concerning package globals..

From perlmod:
Perl provides a mechanism for alternative namespaces to protect packages from stomping on each other's variables. In fact, there's really no such thing as a global variable in Perl. The package
statement declares the compilation unit as being in the given namespace. The scope of the package declaration is from the declaration itself through the end of the enclosing block, eval, or file,
whichever comes first (the same scope as the my() and local() operators). Unqualified dynamic identifiers will be in this namespace, except for those few identifiers that if unqualified, default to
the main package instead of the current one as described below. A package statement affects only dynamic variables--including those you've used local() on--but not lexical variables created with my().

I'm relatively new to Perl compared to all you guys. It appears
to me that 'my()' is a late bloomer to Perl, you know? Lexical's.
I have no idea what Perl means by a lexical. I know scoping thouroughly.
To me, lexical's were dropped in as an add-on to un-confuse what appears
to be a massive namespace problem that existed with every variable being
dropped into the hash, and the look-up overhead nightmare performance hit,
collissions with other namespaces, etc..

I've heard all the 'you better use strict/warnings' mantra. So I always do,
and it helps alot. But you can't define a package global with strict on, so
I don't. I use all file-scoped lexical globals. I really don't have the need
for users to see my file scoped variables anyway.

So use strict is something I usually don't see in Modules (.pm files). Sure
enough, there are non-lexical scalar variables. So what is strict, just for
debug? Probably is a way to tell it to go lightly on package globals huh?

Package FunStuff;

$IwannaBeApackageGlobal = "don't use strict then";

use Strict; # down here then..

Its all clear as muddy waters.

Thanks!

sln
 
S

sln

and it is named main::




You are incorrect. Twice.

If it was a package variable, then it would be in the main:: package.

But it is a lexical variable, and lexical variables are not in any package.

Maybe, but where does my $variable go? Into the Package::Lexical namespace?
Where does scoped variables go, what keeps track of them... the stack structure?

sln
 
T

Tad J McClellan

It appears
to me that 'my()' is a late bloomer to Perl,


Lexical variables were introduced in Perl 5.

In Perl 4 and before, package variables where all there was.

To me, lexical's were dropped in as an add-on to un-confuse what appears
to be a massive namespace problem that existed with every variable being
dropped into the hash, and the look-up overhead nightmare performance hit,
collissions with other namespaces, etc..


You are correct!

However the primary benefit of using lexical variables is for the programmer,
rather than for the interpreter.

I've heard all the 'you better use strict/warnings' mantra. So I always do,
and it helps alot.


Here is another mantra that will serve you well:

Always prefer lexical variables (my) over package variables (our),
except when you can't.

But you can't define a package global with strict on,


Yes you can.

-------------------
#!/usr/bin/perl
use warnings;
use strict;

$main::var = 'some value';
print "$main::var\n";
-------------------

Works fine...

so
I don't. I use all file-scoped lexical globals. I really don't have the need
for users to see my file scoped variables anyway.


Then you don't *want* them to be package variables.

Since you _can_ use lexical variables, then following the mantra,
that is what you should use.

So use strict is something I usually don't see in Modules (.pm files).


You are not looking in the right place then.

I dashed off this crude test:

-------------------
#!/usr/bin/perl
use warnings;
use strict;
use File::Find;

my @files;
find( \&is_module, @INC );
my $module_cnt = @files;
print "$module_cnt module files found\n";

my $strict_cnt;
foreach my $file ( @files ) {
$strict_cnt++ if qx/grep -l 'use strict;' $file/;
}

print "$strict_cnt module files found that use strict\n";

my $percent = sprintf '%.0f', ($strict_cnt / $module_cnt) * 100;
print "$percent% of modules have strict enabled\n";

sub is_module {
push @files, $File::Find::name if /\.pm$/;
}
-------------------


About 80% of the modules on my system appear to have strict enabled.

So what is strict, just for
debug? Probably is a way to tell it to go lightly on package globals huh?

Package FunStuff;


Please post Real Perl Code rather than attempt to paraphrase Perl code.

Case matters.

$IwannaBeApackageGlobal = "don't use strict then";

use Strict; # down here then..


Putting the "use strict" (not "use Strict", case matters) "down here"
will not change anything. You'll get the same error regardless of
where in the file the "use strict" statement is.

To use your package variable with strict enabled you must either declare it:

our $IwannaBeApackageGlobal = "do use strict";

or use the explicit package name:

$FunStuff::IwannaBeApackageGlobal = "do use strict";
 
U

Uri Guttman

s> I agree with everything you said. 'File scoped globals', ie lexical's
s> in the outer scope. I'm not sure package globals are available for
s> access throughout the program without explicetly including the namespace
s> hash key, unless its imported (aliased) withing a use statement.
s> At least that's what I get out of the docs. I'm probably wrong, dunno.


nope. you can access any package global anywhere and at anytime. sure
you will need the package name (explicitly or in a symref) but those
can't be hidden like lexicals. local() will push a new dynamically
scoped value onto a package global but it doesn't hide the symbol.

s> I'm relatively new to Perl compared to all you guys. It appears to
s> me that 'my()' is a late bloomer to Perl, you know? Lexical's. I
s> have no idea what Perl means by a lexical. I know scoping
s> thouroughly. To me, lexical's were dropped in as an add-on to
s> un-confuse what appears to be a massive namespace problem that
s> existed with every variable being dropped into the hash, and the
s> look-up overhead nightmare performance hit, collissions with other
s> namespaces, etc..

perl 5 has always had my and perl4 did not. so i wouldn't call lexicals
drop in but rather one of the major improvements in perl5 (along with
references, OO and many other things).

s> I've heard all the 'you better use strict/warnings' mantra. So I
s> always do, and it helps alot. But you can't define a package global
s> with strict on, so I don't. I use all file-scoped lexical
s> globals. I really don't have the need for users to see my file
s> scoped variables anyway.

you can 'define' or better yet declare a package global with our. it
creates a lexical short name for use in the current scope. any our
variable is simple a shortname with the current package implied for its
fully qualified name.

s> So use strict is something I usually don't see in Modules (.pm
s> files). Sure enough, there are non-lexical scalar variables. So
s> what is strict, just for debug? Probably is a way to tell it to go
s> lightly on package globals huh?

strict should be on in modules too. leaving it out it means the author
was lazy or couldn't find a way to handle strict issues.

s> Package FunStuff;

s> $IwannaBeApackageGlobal = "don't use strict then";

nope. either use our, use 'vars' or a fully qualified name:

Package FunStuff;

$IwannaBeApackageGlobal = "no strict here";

use strict ;

our $IwannaBeApackageGlobal = "use strict then";
$FunStuff::IwannaBeApackageGlobal = "fine under strict too";
$IwannaBeApackageGlobal = "still fine under strict" ;

all four of those refer to the exact same variable in the same package.

uri
 
U

Uri Guttman

s> Maybe, but where does my $variable go? Into the Package::Lexical
s> namespace? Where does scoped variables go, what keeps track of
s> them... the stack structure?

lexical names effectively disappear after the compile phase (not
technically true but good enough for this thread). you can't access a
lexical variable at runtime with a dynamic name as there is no record of
that name available to the code. there is no such thing as just 'scoped
variables'. either they are lexical or dynamic in scope. lexicals are
not on a stack but are allocated from a heap. sub call stacks track them
and will free them upon exit of their blocks as long as they have a zero
reference count.

uri
 
U

Uri Guttman

TJM> Putting the "use strict" (not "use Strict", case matters) "down
TJM> here" will not change anything. You'll get the same error
TJM> regardless of where in the file the "use strict" statement is.

not exactly. strict like all lexical stuff works from its line to the
end of the current scope. an old OO trick was to set @ISA before the
strict line.

package Foo ;
@ISA = qw( Bar ) ;
use strict ;
....

i would rather see use lib or our @ISA today and keep strict at the top
where it belongs.

package Foo ;
use strict ;

our @ISA = qw( Bar ) ;
#or
use lib 'Bar' ; # this also loads Bar.pm for you

uri
 
S

sln

s> I agree with everything you said. 'File scoped globals', ie lexical's
s> in the outer scope. I'm not sure package globals are available for
s> access throughout the program without explicetly including the namespace
s> hash key, unless its imported (aliased) withing a use statement.
s> At least that's what I get out of the docs. I'm probably wrong, dunno.


nope. you can access any package global anywhere and at anytime. sure
you will need the package name (explicitly or in a symref) but those
can't be hidden like lexicals. local() will push a new dynamically
scoped value onto a package global but it doesn't hide the symbol.

s> I'm relatively new to Perl compared to all you guys. It appears to
s> me that 'my()' is a late bloomer to Perl, you know? Lexical's. I
s> have no idea what Perl means by a lexical. I know scoping
s> thouroughly. To me, lexical's were dropped in as an add-on to
s> un-confuse what appears to be a massive namespace problem that
s> existed with every variable being dropped into the hash, and the
s> look-up overhead nightmare performance hit, collissions with other
s> namespaces, etc..

perl 5 has always had my and perl4 did not. so i wouldn't call lexicals
drop in but rather one of the major improvements in perl5 (along with
references, OO and many other things).

s> I've heard all the 'you better use strict/warnings' mantra. So I
s> always do, and it helps alot. But you can't define a package global
s> with strict on, so I don't. I use all file-scoped lexical
s> globals. I really don't have the need for users to see my file
s> scoped variables anyway.

you can 'define' or better yet declare a package global with our. it
creates a lexical short name for use in the current scope. any our
variable is simple a shortname with the current package implied for its
fully qualified name.

s> So use strict is something I usually don't see in Modules (.pm
s> files). Sure enough, there are non-lexical scalar variables. So
s> what is strict, just for debug? Probably is a way to tell it to go
s> lightly on package globals huh?

strict should be on in modules too. leaving it out it means the author
was lazy or couldn't find a way to handle strict issues.

s> Package FunStuff;

s> $IwannaBeApackageGlobal = "don't use strict then";

nope. either use our, use 'vars' or a fully qualified name:

Package FunStuff;

$IwannaBeApackageGlobal = "no strict here";

use strict ;

our $IwannaBeApackageGlobal = "use strict then";
$FunStuff::IwannaBeApackageGlobal = "fine under strict too";
$IwannaBeApackageGlobal = "still fine under strict" ;

all four of those refer to the exact same variable in the same package.

uri

I have to thank you and Tad for all the help. The docs can be heavy at times.
I'm using 5.8.8 still, think I upgraded to 5.10 at one point but
the html docs were off my readable window, the wrap didn't reflect the scroll position,
so I reverted.

I understand now. I tried all package global declaration methods and tested them..
Just popped them on top of a pre-existing package I already have. All worked, but the
fully qualified name would take a non-existent package name as well. It might be that
if the module isin't found, it loads it into the main:: namespace without warning. Dunno.

I tested en-mass, here (printed to STDERR because the module produces output
I redirect from the command line) is what I got:

Package FunStuff;
use vars qw($IwannaBeApackageGlobal2);

our $IwannaBeApackageGlobal = "use strict then"; # works
$IwannaBeApackageGlobal2 = "use strict then = 2"; # works
$hhh::IwannaBeApackageGlobal3 = "use strict then = 3"; # works, but have to use qulified name all the time

print STDERR $IwannaBeApackageGlobal,"\n";
print STDERR $IwannaBeApackageGlobal2,"\n";
print STDERR $hhh::IwannaBeApackageGlobal3,"\n";

# output:
# use strict then
# use strict then = 2
# use strict then = 3

I had no idea 'vars' was used as a pragma to predeclare package globals. Depricated, use 'our' instead.
From CPAN:
pragma 'vars' reference: http://search.cpan.org/~rgarcia/perl-5.10.0/lib/vars.pm

NOTE: For variables in the current package, the functionality provided by this pragma has been superseded by our declarations, available in Perl v5.6.0 or later.
This will predeclare all the variables whose names are in the list, allowing you to use them under "use strict", and disabling any typo warnings.


sln
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top