List Variable becomes undefined inexplicably
List Variable becomes undefined inexplicably
am 20.09.2007 02:32:03 von mattbreedlove
Using Perl v5.8.4
This type of problem has plagued me over the years several times. Each
time I have had to rearrange the way that my PERL script was designed
to work around it.
At this point I think its a bug or something really strange.
I was able to reproduce it with the test script below.
The issue is that a global list variable that is built inside
subroutine A, iterated over in a foreach loop in subroutine B, is then
magically undefined after the foreach loop if the loop contains a
command pipe with a while loop.
According the laws of PERL that I am used to when you run the below
script you *should* get:
main_before-ITERATE_HOSTS -apple orange durian-
start_inside_ITERATE_HOSTS -apple orange durian-
end_inside_ITERATE_HOSTS -apple orange durian-
main_after-ITERATE_HOSTS -apple orange durian-
However instead you get
main_before-ITERATE_HOSTS -apple orange durian-
start_inside_ITERATE_HOSTS -apple orange durian-
end_inside_ITERATE_HOSTS - -
main_after-ITERATE_HOSTS - -
Any ideas?
Here is the test script:
#!perl
SETUP_HOSTS();
print "main_before-ITERATE_HOSTS -@SLAVE_HOSTS-\n";
ITERATE_HOSTS();
print "main_after-ITERATE_HOSTS -@SLAVE_HOSTS-\n";
sub SETUP_HOSTS {
push(@SLAVE_HOSTS, apple);
push(@SLAVE_HOSTS, orange);
push(@SLAVE_HOSTS, durian);
}
sub ITERATE_HOSTS {
print "start_inside_ITERATE_HOSTS -@SLAVE_HOSTS-\n";
foreach (@SLAVE_HOSTS) {
$REMOTE_HOST="$_";
#open(CMD, "$SSH $REMOTE_HOST 'do some stuff'|");
while() {
chomp;
$LINE="$_";
if ( "$LINE" =~ /service id\=/ ) {
print "blah\n";
}
}
close(CMD);
}
print "end_inside_ITERATE_HOSTS -@SLAVE_HOSTS-\n";
}
Re: List Variable becomes undefined inexplicably
am 20.09.2007 03:08:52 von kenslaterpa
On Sep 19, 8:32 pm, mattbreedl...@yahoo.com wrote:
> Using Perl v5.8.4
> This type of problem has plagued me over the years several times. Each
> time I have had to rearrange the way that my PERL script was designed
> to work around it.
>
> At this point I think its a bug or something really strange.
> I was able to reproduce it with the test script below.
>
> The issue is that a global list variable that is built inside
> subroutine A, iterated over in a foreach loop in subroutine B, is then
> magically undefined after the foreach loop if the loop contains a
> command pipe with a while loop.
>
> According the laws of PERL that I am used to when you run the below
> script you *should* get:
> main_before-ITERATE_HOSTS -apple orange durian-
> start_inside_ITERATE_HOSTS -apple orange durian-
> end_inside_ITERATE_HOSTS -apple orange durian-
> main_after-ITERATE_HOSTS -apple orange durian-
>
> However instead you get
> main_before-ITERATE_HOSTS -apple orange durian-
> start_inside_ITERATE_HOSTS -apple orange durian-
> end_inside_ITERATE_HOSTS - -
> main_after-ITERATE_HOSTS - -
>
> Any ideas?
>
> Here is the test script:
>
> #!perl
use strict;
use warnings;
>
my @SLAVE_HOSTS;
> SETUP_HOSTS();
> print "main_before-ITERATE_HOSTS -@SLAVE_HOSTS-\n";
> ITERATE_HOSTS();
> print "main_after-ITERATE_HOSTS -@SLAVE_HOSTS-\n";
>
> sub SETUP_HOSTS {
>
Note that you will be forced to quote barewords when using strict:
> push(@SLAVE_HOSTS, apple);
> push(@SLAVE_HOSTS, orange);
> push(@SLAVE_HOSTS, durian);
>
> }
>
> sub ITERATE_HOSTS {
> print "start_inside_ITERATE_HOSTS -@SLAVE_HOSTS-\n";
Here is part of your problem - using the default variable ($_)
It would be better to define a new variable
foreach my $slave (@SLAVE_HOSTS)
> foreach (@SLAVE_HOSTS) {
Useless use of quotes
my $REMOTE_HOST = $_;
> $REMOTE_HOST="$_";
>
> #open(CMD, "$SSH $REMOTE_HOST 'do some stuff'|");
Note that you are using $_ as the loop variable here.
This is not good, as $_ is one of the elements of @SLAVE_HOSTS (see
above foreach)
When you modify $_ you modify an element of @SLAVE_HOSTS - essentially
you are 'undef' ing the whole array since the 'OPEN' statement is
commented.
> while() {
> chomp;
Useless use of quotes
my $LINE = $_;
> $LINE="$_";
Useless use of quotes also no need to backslash the equal sign
> if ( "$LINE" =~ /service id\=/ ) {
> print "blah\n";
> }
> }
> close(CMD);
> }
> print "end_inside_ITERATE_HOSTS -@SLAVE_HOSTS-\n";
>
> }
HTH, Ken
Re: List Variable becomes undefined inexplicably
am 20.09.2007 03:18:09 von Tad McClellan
mattbreedlove@yahoo.com wrote:
> the way that my PERL script
There is no PERL.
There is a Perl and there is a perl.
> At this point I think its a bug or something really strange.
The really strange something is your code.
> Any ideas?
Enable warnings when developing Perl programs.
> push(@SLAVE_HOSTS, apple);
You should put quotes around strings in Perl programs.
> $REMOTE_HOST="$_";
Whitespace is not a scarce resource, feel free to use as much of it
as you like to help make your code easier to read and understand.
perldoc -q vars
Whatâs wrong with always quoting "$vars"?
So that should be:
$REMOTE_HOST = $_;
> #open(CMD, "$SSH $REMOTE_HOST 'do some stuff'|");
> while() {
You are not going to get interesting input when you read
from a filehandle that has not been open()ed.
> chomp;
> $LINE="$_";
If you want the input in $LINE, then just put it there rather than
put it somewhere else and then move it there:
while ( $LINE = ) {
chomp $LINE;
If you want to be taken seriously, then write an example that
illustrates your problem with
use warnings;
use strict;
near the top of the program.
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
Re: List Variable becomes undefined inexplicably
am 20.09.2007 17:52:33 von mattbreedlove
The only reason the open command was commented was so that anyone
could run the test script to reproduce the problem. I tested the test
script with or without the commented "open" command so its not like
the array is getting undefined by the absence of input to the while
loop. It is certainly not the root cause.
I believe there is a place for strict and warnings. That place is not
necessarily in a quick test script to illustrate a completely
unrelated problem. Thanks
So the question remains, why is this happening? I appreciate the
suggestions to define a new variable in the instantiation of the
foreach/while loops, but the fact is that "should" not be required.
foreach (@SLAVE_HOSTS) {
chomp;
$REMOTE_HOST="$_";
open(CMD, "ping $REMOTE_HOST|");
while() {
chomp;
$LINE="$_";
}
}
print "@SLAVE_HOSTS\n";
PERL should be able to keep track of the frame of reference and values
for two discreet "$_" in nested iterative loops without blowing away a
parent array
This should be the same:
while() {
chomp;
$LINE="$_";
}
as this:
while ( $LINE = ) {
chomp $LINE;
Such a "waste" of a precious line when it could be done with one line
less, but again the fact remains that this should work. Correct?
Re: List Variable becomes undefined inexplicably
am 20.09.2007 18:54:59 von nobull67
On Sep 20, 4:52 pm, mattbreedl...@yahoo.com wrote:
> PERL should be able to keep track of the frame of reference and values
> for two discreet "$_" in nested iterative loops without blowing away a
> parent array
What you are actually saying is that the implicit assignment to $_ in
while() should be implicit _localisation_ and assignment.
No argument from me there. If I had a time machine I'd go back and fix
it but there are probably moderately good reasons why it would be bad
to fix it now.
I always do a local(*_) before a while loop using implicit assignment
of $_ and I suggest that everyone should do so (or not use the
implicit assignment at all).
Do not be temped to do local($_) as nasty things will happen if the
"parent array" happens to be tied.
BTW: Please don't call Perl "PERL" as you'll just needlessly piss
people off.
Re: List Variable becomes undefined inexplicably
am 20.09.2007 19:01:36 von Dummy
mattbreedlove@yahoo.com wrote:
>
> PERL should be able to keep track of the frame of reference and values
> for two discreet "$_" in nested iterative loops without blowing away a
> parent array
This "PERL" you speak of may be able to do that but here we use Perl which has
only one $_ variable.
John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
Re: List Variable becomes undefined inexplicably
am 20.09.2007 19:10:46 von Jim Gibson
In article <1190303553.751484.24640@z24g2000prh.googlegroups.com>,
wrote:
> The only reason the open command was commented was so that anyone
> could run the test script to reproduce the problem. I tested the test
> script with or without the commented "open" command so its not like
> the array is getting undefined by the absence of input to the while
> loop. It is certainly not the root cause.
No, the open is not the root cause. The root cause is the input
operator that you did _not_ comment out. In general, it is best
to post only relevant code, replacing such things as reading external
files with the equivalent assignment statements, for example, or using
the special file handle so people can cut-and-paste your
program.
>
> I believe there is a place for strict and warnings. That place is not
> necessarily in a quick test script to illustrate a completely
> unrelated problem. Thanks
Fewer people will analyze your code if you don't have use strict. You
do want to get help, don't you? How can you be sure what is related and
what is not?
>
> So the question remains, why is this happening? I appreciate the
> suggestions to define a new variable in the instantiation of the
> foreach/while loops, but the fact is that "should" not be required.
>
> foreach (@SLAVE_HOSTS) {
> chomp;
> $REMOTE_HOST="$_";
>
> open(CMD, "ping $REMOTE_HOST|");
> while() {
> chomp;
> $LINE="$_";
> }
> }
> print "@SLAVE_HOSTS\n";
>
> PERL should be able to keep track of the frame of reference and values
> for two discreet "$_" in nested iterative loops without blowing away a
> parent array
Perl could, were it implemented that way, but it was not and does not.
You need to use a language the way it was implemented, not the way you
think it _should_ have been implemented. If you want a local version of
$_, use 'local $_;'.
>
> This should be the same:
> while() {
> chomp;
> $LINE="$_";
> }
>
> as this:
>
> while ( $LINE = ) {
> chomp $LINE;
But the former has a side-effect, as you have discovered. It overwrites
the global $_ variable, which is aliased to a member of the
@SLAVE_HOSTS array. Since you do this for each element of @SLAVE_HOSTS,
and you are reading from an opening file handle, all of the members are
set to undef.
>
> Such a "waste" of a precious line when it could be done with one line
> less, but again the fact remains that this should work. Correct?
>
No, not correct. It should not work according to Perl's well-known
feature of using the global $_ variable as the default for many Perl
operations.
--
Jim Gibson
Posted Via Usenet.com Premium Usenet Newsgroup Services
----------------------------------------------------------
** SPEED ** RETENTION ** COMPLETION ** ANONYMITY **
----------------------------------------------------------
http://www.usenet.com
Re: List Variable becomes undefined inexplicably
am 20.09.2007 19:32:06 von kenslaterpa
On Sep 20, 11:52 am, mattbreedl...@yahoo.com wrote:
> The only reason the open command was commented was so that anyone
> could run the test script to reproduce the problem. I tested the test
> script with or without the commented "open" command so its not like
> the array is getting undefined by the absence of input to the while
> loop. It is certainly not the root cause.
>
> I believe there is a place for strict and warnings. That place is not
> necessarily in a quick test script to illustrate a completely
> unrelated problem. Thanks
I 'always' use strict and warnings. How do you know you don't have a
problem that is related until you try it?
>
> So the question remains, why is this happening?
Because of the way the foreach loop works - issue the command "perldoc
perlsyn" for more information.
>I appreciate the
> suggestions to define a new variable in the instantiation of the
> foreach/while loops, but the fact is that "should" not be required.
Playing the devil's advocate here. How would you refer to the $_
variable from the outer loop in the inner loop? Are you going to
force a label on the loops, so you can say OUTER_LOOP:$_ ?
>
> foreach (@SLAVE_HOSTS) {
> chomp;
> $REMOTE_HOST="$_";
>
> open(CMD, "ping $REMOTE_HOST|");
> while() {
> chomp;
> $LINE="$_";
> }}
>
> print "@SLAVE_HOSTS\n";
>
> PERL should be able to keep track of the frame of reference and values
> for two discreet "$_" in nested iterative loops without blowing away a
> parent array
>
> This should be the same:
> while() {
> chomp;
> $LINE="$_";
>
> }
>
> as this:
>
> while ( $LINE = ) {
> chomp $LINE;
>
> Such a "waste" of a precious line when it could be done with one line
> less, but again the fact remains that this should work. Correct?
Not sure what you are referring to by 'this'. If you mean that $LINE
should contain the same value as $_ within the loop, I would say
yes.
Ken
Re: List Variable becomes undefined inexplicably
am 20.09.2007 21:25:03 von rvtol+news
Tad McClellan schreef:
> perldoc -q vars
>
> Whatâ?Ts wrong with always quoting "$vars"?
YM: LANG="" perldoc -q vars
--
Affijn, Ruud
"Gewoon is een tijger."
Re: List Variable becomes undefined inexplicably
am 20.09.2007 21:36:22 von Charlton Wilbur
>>>>> "mb" == mattbreedlove writes:
mb> I believe there is a place for strict and warnings. That
mb> place is not necessarily in a quick test script to illustrate
mb> a completely unrelated problem. Thanks
However, it *is* in a script you are asking human beings to help you
with; if you haven't made adequate use of the automatic tools
available to you, why are you wasting other people's time?
Charlton
--
Charlton Wilbur
cwilbur@chromatico.net
Re: List Variable becomes undefined inexplicably
am 20.09.2007 22:37:54 von Abigail
_
John W. Krahn (dummy@example.com) wrote on VCXXXIII September MCMXCIII in
:
;; mattbreedlove@yahoo.com wrote:
;; >
;; > PERL should be able to keep track of the frame of reference and values
;; > for two discreet "$_" in nested iterative loops without blowing away a
;; > parent array
;;
;; This "PERL" you speak of may be able to do that but here we use Perl which h
;; only one $_ variable.
The perl on my box has two:
$ perl -wE '$_ = 1; {my $_ = 2; say $_; say $::_}'
2
1
Abigail
--
perl -we '$@="\145\143\150\157\040\042\112\165\163\164\040\141\156\15 7\164".
"\150\145\162\040\120\145\162\154\040\110\141\143\153\145\16 2".
"\042\040\076\040\057\144\145\166\057\164\164\171";`$@`'
Re: List Variable becomes undefined inexplicably
am 21.09.2007 00:32:02 von mattbreedlove
Honestly, I am intrigued by this passion about not referring to PERL
in caps. Correct me if I am wrong, but PERL is an Acronym for
Practical Extraction and Reporting Language.
Generally, acronyms are written in caps. If anything I could see
saying that it should be written P.E.R.L
So what is all this frustration about?
Re: List Variable becomes undefined inexplicably
am 21.09.2007 00:49:17 von Keith Keller
On 2007-09-20, mattbreedlove@yahoo.com wrote:
> Honestly, I am intrigued by this passion about not referring to PERL
> in caps. Correct me if I am wrong, but PERL is an Acronym for
> Practical Extraction and Reporting Language.
http://en.wikipedia.org/wiki/Perl#Name
--keith
--
kkeller-usenet@wombat.san-francisco.ca.us
(try just my userid to email me)
AOLSFAQ=http://www.therockgarden.ca/aolsfaq.txt
see X- headers for PGP signature information
Re: List Variable becomes undefined inexplicably
am 21.09.2007 00:51:10 von Uri Guttman
>>>>> "m" == mattbreedlove writes:
m> Honestly, I am intrigued by this passion about not referring to
m> PERL in caps. Correct me if I am wrong, but PERL is an Acronym for
m> Practical Extraction and Reporting Language.
you are wrong. read the perlfaq for the real history of the name.
m> Generally, acronyms are written in caps. If anything I could see
m> saying that it should be written P.E.R.L
wronger.
it is Perl for the language and perl for the program. never PERL which
marks you as someone who doesn't know Perl.
m> So what is all this frustration about?
being technically correct and pedantic is a useful attribute in a
programmer. using the correct name is a point that is worth defending.
uri
--
Uri Guttman ------ uri@stemsystems.com -------- http://www.stemsystems.com
--Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
Re: List Variable becomes undefined inexplicably
am 21.09.2007 02:12:22 von benkasminbullock
On Sep 21, 2:10 am, Jim Gibson wrote:
> In article <1190303553.751484.24...@z24g2000prh.googlegroups.com>,
>
> wrote:
> > The only reason the open command was commented was so that anyone
> > could run the test script to reproduce the problem. I tested the test
> > script with or without the commented "open" command so its not like
> > the array is getting undefined by the absence of input to the while
> > loop. It is certainly not the root cause.
>
> No, the open is not the root cause. The root cause is the input
> operator that you did _not_ comment out. In general, it is best
> to post only relevant code, replacing such things as reading external
> files with the equivalent assignment statements, for example, or using
> the special file handle so people can cut-and-paste your
> program.
>
>
>
> > I believe there is a place for strict and warnings. That place is not
> > necessarily in a quick test script to illustrate a completely
> > unrelated problem. Thanks
>
> Fewer people will analyze your code if you don't have use strict.
>From the number of responses to the original poster's query, it
actually looks like the opposite: many more people will analyze one's
code if one doesn't have "use strict;".
Just an observation.
Re: List Variable becomes undefined inexplicably
am 21.09.2007 02:29:41 von mattbreedlove
> it is Perl for the language and perl for the program. never PERL which
> marks you as someone who doesn't know Perl.
Is that kind of like saying someone must not know how to drive well
unless they know how to fix cars?
Re: List Variable becomes undefined inexplicably
am 21.09.2007 03:32:07 von Tad McClellan
mattbreedlove@yahoo.com wrote:
> I believe there is a place for strict and warnings.
That's nice but it is not relevant to getting someone to examine
your problem.
What is relevant to getting the interest of others is what the
_others_ think.
I've been here for quite some time, I know how a program without
warnings and strict are received here (the most common reaction
is to simply move on to the next question).
I was trying to help you avoid being ignored. Disregard my
comments if being ignored does not concern you.
> That place is not
> necessarily in a quick test script to illustrate a completely
> unrelated problem.
warnings and strictures very often find bugs in programs. Many
people will find it demeaning to be asked to do the work of a machine.
It is inconsiderate of your audience to post without warnings and strict.
> Thanks
Off to the killfile you go then.
> PERL should be able to keep track of the frame of reference
There is no PERL.
There is a Perl and there is a perl.
> This should be the same:
> while() {
> chomp;
> $LINE="$_";
> }
>
> as this:
>
> while ( $LINE = ) {
> chomp $LINE;
>
> Such a "waste" of a precious line when it could be done with one line
> less,
The number of lines is not the point.
The point is maintainability.
Being direct is easier to read and understand than being circuitous.
--
Tad McClellan
email: perl -le "print scalar reverse qq/moc.noitatibaher\100cmdat/"
Re: List Variable becomes undefined inexplicably
am 21.09.2007 11:50:36 von RedGrittyBrick
mattbreedlove@yahoo.com wrote:
>>it is Perl for the language and perl for the program. never PERL which
>>marks you as someone who doesn't know Perl.
>
>
> Is that kind of like saying someone must not know how to drive well
> unless they know how to fix cars?
>
>
>
No, it is more like drivers being required to understand the difference
between a Ford and a ford.
Re: List Variable becomes undefined inexplicably
am 21.09.2007 16:49:41 von Charlton Wilbur
>>>>> "mb" == mattbreedlove writes:
>> it is Perl for the language and perl for the program. never
>> PERL which marks you as someone who doesn't know Perl.
mb> Is that kind of like saying someone must not know how to drive
mb> well unless they know how to fix cars?
No, it's more like saying that a mechanic who refers to bits of the
engine by the wrong names is unlikely to be competent.
PERL versus Perl or perl is a shibboleth: using the wrong one
indicates that you're likely to be a clueless novice. If you really
want people to think you are a clueless novice, and you really want
people to treat you as a clueless novice, by all means, carry on.
And continuing to use PERL after this has been pointed out generally
marks you as a clueless novice who's stubborn enough to persist in his
cluelessness, which means that wise people will, for the most part,
just silently plonk you.
Honestly, you came here for help, and the people you came to for help,
most of whom have more experience than you, have made a couple
recommendations. Now, the PERL/Perl/perl shibboleth is not really an
important one technically, but the way you react to it is very
telling. More important technically, and more telling, is the way you
reacted to the advice to use strictures and warnings. If you aren't
interested in listening to or following advice, why ask for it?
Charlton
--
Charlton Wilbur
cwilbur@chromatico.net
Re: List Variable becomes undefined inexplicably
am 23.09.2007 05:31:32 von Joe Smith
mattbreedlove@yahoo.com wrote:
> The issue is that a global list variable that is built inside
> subroutine A, iterated over in a foreach loop in subroutine B, is then
> magically undefined after the foreach loop if the loop contains a
> command pipe with a while loop.
Here's an example that has more print() statements to show what's going on.
#!/usr/bin/perl
use strict; use warnings;
my @hosts = qw(alpha delta goofy);
print "Before: \@hosts = (@hosts)\n";
iterate_hosts();
print "After: \@hosts = (@hosts)\n";
sub iterate_hosts {
print " Start of iterate_hosts: \@hosts = (@hosts)\n";
foreach (@hosts) {
print " Top of loop: \$_ = '$_', \@hosts = (@hosts)\n";
$_ = "a line of text\n"; # Simulate while()
$_ = '__'; # Simulate EOF on CMD
print " Bottom of loop: \$_ = '$_', \@hosts = (@hosts)\n";
}
print " End of iterate_hosts: \@hosts = (@hosts)\n";
}
Output:
Before: @hosts = (alpha delta goofy)
Start of iterate_hosts: @hosts = (alpha delta goofy)
Top of loop: $_ = 'alpha', @hosts = (alpha delta goofy)
Bottom of loop: $_ = '__', @hosts = (__ delta goofy)
Top of loop: $_ = 'delta', @hosts = (__ delta goofy)
Bottom of loop: $_ = '__', @hosts = (__ __ goofy)
Top of loop: $_ = 'goofy', @hosts = (__ __ goofy)
Bottom of loop: $_ = '__', @hosts = (__ __ __)
End of iterate_hosts: @hosts = (__ __ __)
After: @hosts = (__ __ __)After: @hosts = ( )
As others have mentioned, using
foreach my $host (@hosts) {...}
or
while(my $line=) {...}
or both will eliminate your problem.
-Joe
Re: List Variable becomes undefined inexplicably
am 23.09.2007 12:59:31 von nobull67
On 20 Sep, 17:54, Brian McCauley wrote:
> Do not be temped to do local($_)
But, I should add, in 5.10 you can do my($_)