Perl Scope problem

Started by Randall Perryalmost 25 years ago7 messagesgeneral
Jump to latest
#1Randall Perry
rgp@systame.com

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

#2hciR nellA
g3pb@alaska.net
In reply to: Randall Perry (#1)
Re: [MacPerl] Perl Scope problem

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!

#3Bart Lateur
bart.lateur@skynet.be
In reply to: Randall Perry (#1)
Re: [MacPerl] Perl Scope problem

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.

#4Michelle Murrain
mpm@norwottuck.com
In reply to: Randall Perry (#1)
Re: Perl Scope problem

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

#5will trillich
will@serensoft.com
In reply to: Michelle Murrain (#4)
Re: Perl Scope problem

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!

#6Jeff Duffy
jeff@alanne.com
In reply to: will trillich (#5)
Re: Perl Scope problem

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

#7Dan Lyke
danlyke@flutterby.com
In reply to: Randall Perry (#1)

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