Обсуждение: Perl Scope problem
I'm baffled by perl's scoping of variables. In the code below, the
$cust_data hash ref is inited outside the while loop. It's then set in the
while with the results of a PgSQL query.
In the if-else statement $cust_data can be seen in the 'if' but not in the
'else' (if I try to print a value in else, $cust_data->{'customer'}, I get
an undeclared variable error).
I understand that by using 'strict' I can't use any global variables.
Can someone explain why this happens and how to make it work right?
use strict;
$cust_data = {};
while ($condition) {
...
$cust_data = get_cust_data();
if ($condition2) {
if (send_mail($cust_data)) {
print $cust_data->{'customer'};
...
}
else {
if (send_mail($cust_data)) {
print $cust_data->{'customer'};
...
}
}
--
Randy Perry
sysTame
Mac Consulting/Sales
On Wednesday 02 May 2001 11:27 pm, Randall Perry wrote:
> I'm baffled by perl's scoping of variables. In the code below, the
> $cust_data hash ref is inited outside the while loop. It's then set in the
> while with the results of a PgSQL query.
>
> In the if-else statement $cust_data can be seen in the 'if' but not in the
> 'else' (if I try to print a value in else, $cust_data->{'customer'}, I get
> an undeclared variable error).
>
> I understand that by using 'strict' I can't use any global variables.
No, my understanding is that it forces you to define variables both local and
global. I've used this statement to declare variables I need throughout a
script using strict:
use vars qw($val $var $value $conf @var_array @val_array %fields_hash);
Michelle
------------
Michelle Murrain, Ph.D.
President
Norwottuck Technology Resources
mpm@norwottuck.com
http://www.norwottuck.com
On Thu, May 03, 2001 at 08:39:18AM -0400, Michelle Murrain wrote:
> On Wednesday 02 May 2001 11:27 pm, Randall Perry wrote:
> > I'm baffled by perl's scoping of variables. In the code below, the
> > $cust_data hash ref is inited outside the while loop. It's then set in the
> > while with the results of a PgSQL query.
> >
> > In the if-else statement $cust_data can be seen in the 'if' but not in the
> > 'else' (if I try to print a value in else, $cust_data->{'customer'}, I get
> > an undeclared variable error).
> >
> > I understand that by using 'strict' I can't use any global variables.
>
> No, my understanding is that it forces you to define variables both local and
> global. I've used this statement to declare variables I need throughout a
> script using strict:
>
> use vars qw($val $var $value $conf @var_array @val_array %fields_hash);
"use vars" takes a list of package globals that you'd like
shortcuts for. instead of having to say 'my::package::name::var'
every time you can just say $var instead.
so scoping SHOULD work as you suspect:
##########################
package Original::Package;
use vars($OMNI);
# package global var
$Original::Package::OMNI = &something();
# same variable here
$OMNI .= &somethingElse();
# lexically local to this file:
my $FileGlobal;
{
my $localVar;
{
my $eensyVar;
# all 4 are visible here
print $eensyVar,$localVar,$FileGlobal,$OMNI;
}
# eensyVar is no longer extant
print $localVar,$FileGlobal,$OMNI;
}
# only FileGlobal and OMNI exist here
print $FileGlobal,$OMNI;
#############################
package Something::Else::Entirely;
# whole 'nother package, but OMNI is till reachable
print $Original::Package::OMNI;
none of which explains randall's quandary.
--
don't visit this page. it's bad for you. take my expert word for it.
http://www.salon.com/people/col/pagl/2001/03/21/spring/index1.html
will@serensoft.com
http://sourceforge.net/projects/newbiedoc -- we need your brain!
http://www.dontUthink.com/ -- your brain needs us!
On Thu, 3 May 2001 11:12:22 -0500, will trillich alluded:
> On Thu, May 03, 2001 at 08:39:18AM -0400, Michelle Murrain wrote:
> "use vars" takes a list of package globals that you'd like
> shortcuts for. instead of having to say 'my::package::name::var'
> every time you can just say $var instead.
Yes, but that (as you mention) still leaves the question of how code that
looks like:
use strict;
$cust_data = {};
even compiles, since he should have gotten a
'Global symbol "$cust_data" requires explicit package name..'
compile-time error.
As noted, the the vars pragma is one way around the issue. If you're using
perl 5.6.0 or higher, you can also use the 'our' declaration, which creates a
lexically (not package) scoped global variable, which is very useful for
creating globals you don't want to keep around for the length of the program.
Jeff
Randall Perry writes:
> I'm baffled by perl's scoping of variables.
You don't give exact error messages, but my guess is that this isn't a
scoping error, you're failing in get_cust_data(), so $cust_data is
undef and not a HASH ref. Imagine this rewritten as:
> $cust_data = {};
>
> while ($condition) {
> ...
>
> $cust_data = undef;
> print $cust_data->{'customer'};
Everyone else is right that all valid Perl programs start out:
#!/usr/bin/perl -Tw
use strict;
Dan
On Wed, 02 May 2001 23:27:28 -0400, Randall Perry wrote:
>I'm baffled by perl's scoping of variables. In the code below, the
>$cust_data hash ref is inited outside the while loop. It's then set in the
>while with the results of a PgSQL query.
>
>In the if-else statement $cust_data can be seen in the 'if' but not in the
>'else' (if I try to print a value in else, $cust_data->{'customer'}, I get
>an undeclared variable error).
No sir. You're wrong. And scoping has nothing to do with it. For this
source file, it is just as if it was a global variable.
>use strict;
>$cust_data = {};
This is an initial setting. Where's the "my"? Or else, do
use vars '$cust_data';
>while ($condition) {
> ...
>
> $cust_data = get_cust_data();
Here's you're throwing away the previous value of $cust_data, and
overwriting it with the return value of get_cust_data(). This just might
return undef, for all I care.
> if ($condition2) {
> if (send_mail($cust_data)) {
> print $cust_data->{'customer'};
This works, so $cust_data has been set properly.
> ...
> }
> else {
> if (send_mail($cust_data)) {
> print $cust_data->{'customer'};
This doesn't. Is there some correlation between the return value of
get_custom_data() and the value of $condition2? There must be. My guess
is that get_custom_data() returned undef.
> ...
> }
>}
Now, in order to make scoping really confusing:
if(my $cust_data = get_cust_data()) {
# do something with it
} else {
...
}
Now, in the "else" part, the lexical variable $cust_data can still be
seen! So its scope is not limited to the "if" block, but it includes the
"else" block, and any "elsif" blocks in between.
--
Bart.
think this will work ...
use strict;
my ($cust_data) = {};
my ($condition, $condition2);
while ($condition) {
#...
$cust_data = get_cust_data();
if ($condition2) {
if (send_mail($cust_data)) {
print $cust_data->{'customer'};
# ...
}
}
else {
if (send_mail($cust_data)) {
print $cust_data->{'customer'};
#...
}
}
}
> use strict;
> $cust_data = {};
>
> while ($condition) {
> ...
>
> $cust_data = get_cust_data();
>
> if ($condition2) {
> if (send_mail($cust_data)) {
> print $cust_data->{'customer'};
> ...
>
> }
> else {
>
> if (send_mail($cust_data)) {
> print $cust_data->{'customer'};
> ...
>
> }
> }
- hcir
mailto:g3pb@alaska.net
Made with a Mac!