Обсуждение: 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!