List Variable becomes undefined inexplicably

Discussion in 'Perl Misc' started by mattbreedlove@yahoo.com, Sep 20, 2007.

  1. Guest

    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(<CMD>) {
    chomp;
    $LINE="$_";
    if ( "$LINE" =~ /service id\=/ ) {
    print "blah\n";
    }
    }
    close(CMD);
    }
    print "end_inside_ITERATE_HOSTS -@SLAVE_HOSTS-\n";

    }
     
    , Sep 20, 2007
    #1
    1. Advertising

  2. kens Guest

    On Sep 19, 8:32 pm, 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(<CMD>) {
    > 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
     
    kens, Sep 20, 2007
    #2
    1. Advertising

  3. Guest

    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(<CMD>) {
    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(<CMD>) {
    chomp;
    $LINE="$_";
    }

    as this:

    while ( $LINE = <CMD> ) {
    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?
     
    , Sep 20, 2007
    #3
  4. On Sep 20, 4:52 pm, 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(<FILEHANDLE>) 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.
     
    Brian McCauley, Sep 20, 2007
    #4
  5. 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
     
    John W. Krahn, Sep 20, 2007
    #5
  6. kens Guest

    On Sep 20, 11:52 am, 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(<CMD>) {
    > 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(<CMD>) {
    > chomp;
    > $LINE="$_";
    >
    > }
    >
    > as this:
    >
    > while ( $LINE = <CMD> ) {
    > 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
     
    kens, Sep 20, 2007
    #6
  7. Dr.Ruud Guest

    Tad McClellan schreef:

    > perldoc -q vars
    >
    > Whatâ?Ts wrong with always quoting "$vars"?


    YM: LANG="" perldoc -q vars

    --
    Affijn, Ruud

    "Gewoon is een tijger."
     
    Dr.Ruud, Sep 20, 2007
    #7
  8. >>>>> "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
     
    Charlton Wilbur, Sep 20, 2007
    #8
  9. Guest

    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?
     
    , Sep 20, 2007
    #9
  10. Uri Guttman Guest

    >>>>> "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 ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Sep 20, 2007
    #10
  11. Guest

    On Sep 21, 2:10 am, Jim Gibson <> wrote:
    > In article <>,
    >
    > <> 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 <CMD> 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 <DATA> 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.
     
    , Sep 21, 2007
    #11
  12. Guest

    > 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?
     
    , Sep 21, 2007
    #12
  13. <> 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(<CMD>) {
    > chomp;
    > $LINE="$_";
    > }
    >
    > as this:
    >
    > while ( $LINE = <CMD> ) {
    > 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/"
     
    Tad McClellan, Sep 21, 2007
    #13
  14. 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.
     
    RedGrittyBrick, Sep 21, 2007
    #14
  15. >>>>> "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
     
    Charlton Wilbur, Sep 21, 2007
    #15
  16. 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($_)
     
    Brian McCauley, Sep 23, 2007
    #16
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    9
    Views:
    981
    Juha Nieminen
    Aug 22, 2007
  2. AAaron123
    Replies:
    9
    Views:
    639
    AAaron123
    Mar 18, 2009
  3. Stef Mientki

    and becomes or and or becomes and

    Stef Mientki, May 22, 2011, in forum: Python
    Replies:
    9
    Views:
    318
    Chris Angelico
    May 28, 2011
  4. Taylor Venable

    variable bewilderingly becomes undefined

    Taylor Venable, Oct 17, 2007, in forum: Perl Misc
    Replies:
    14
    Views:
    169
    Taylor Venable
    Oct 18, 2007
  5. Tim Streater
    Replies:
    3
    Views:
    649
    Evertjan.
    Dec 19, 2011
Loading...

Share This Page