Galen has asked for the wisdom of the Perl Monks concerning the following question:

OK - I am not understanding something very rudimentary about loop control. Given the following:
foreach(@tmp) { if (conditionA) { next; } elsif (conditionB) { &do_something; } }
What I'd like to do is check each element of @tmp one by one, and if it meets a conditionA, move on and begin looking at the next element of the array. This isn't working, however. I get the conditionB check whether or not conditionA is met. Thanks in advance - I know this is probably a stupid question.

Replies are listed 'Best First'.
Re: loop control
by dsheroh (Monsignor) on May 22, 2002 at 14:39 UTC
    What does conditionA say? The basic structure you've got here looks like it should work, so I'm inclined to suspect that conditionA always evaluates as false.

    Also, if this is the entire loop (i.e., you're not doing anything else after conditionB's &do_something), you may want to consider rewriting it as

    foreach (@tmp) { $do_something if !conditionA && conditionB }
      Here is the actual code:
      $out = "<?xml version="1.0" encoding="utf-8"?>"; @tmp = split /</, $out; foreach(@tmp) { if (substr($_, 0, 1) eq "?") { next; } elsif (substr($_, 0, 1) eq "!") { &more_code; } }
      What this is doing is parsing xml. Note that the leading "<" has already been stripped by the split function. The contents of $tmp here are:
      ?xml version="1.0" encoding="utf-8"?>
      If I test whether the condition passes or not by simply printing something like "it passed", then I see this.. so I know it's passing the condition.
        first of all, why not using regexp for parsing the string:
        if (/^\?/) { next; } elsif (/^\!/) { rest of the code ; }
        It's much more clear, efficient and fast.
        secondly, you have a problem with the double quotes inside your string, put single quote as outer quotes.
        and third, after fixing the quotes problem it worked for me, I tried it myself.

        Thanks.

        Hotshot
        Your code as posted (almost) works. After modifying it to
        #!/usr/bin/perl -w use strict; my $out = '<?xml version="1.0" encoding="utf-8"?>'; my @tmp = split /</, $out; foreach(@tmp) { if (substr($_, 0, 1) eq "?") { print "conditionA matched - looping!\n"; next; } elsif (substr($_, 0, 1) eq "!") { print "conditionB matched\n"; } print "End of loop\n"; }
        I get the output
        End of loop conditionA matched - looping!
        as expected. (Note that the split is returning a list of two scalars, not just one: the 0 characters before the < and the n characters after it.)

        Side note: That feels a lot like C. Changing your tests to if (/^\?/) and if (/^!/) would feel perlier. Should work either way, though.

Re: loop control
by broquaint (Abbot) on May 22, 2002 at 14:43 UTC
    Are you sure your first conditional is correct? The next loop control statement will go to the next iteration in the current block, which in your case is the immediate foreach loop. Here's an example of some code which works as one would expect
    my @l = qw(foo bar baz quux); foreach (@l) { if(index($_, 'a') > -1) { next; } else { print $_, $/; } } __output__ foo quux
    So we can see that next is being called when $_ contained an 'a'.

    Also this might be a better way to loop through your list

    &do_something foreach grep { (! conditionA) && conditionB } @tmp;
    The grep filters out any elements that don't meet conditionA but do meet conditionB, which is basically what your example loop does.
    HTH

    _________
    broquaint

      Using grep is a good suggestion, but I don't think it'd work for me in this case because the array typically consists of nested values. In other words, $tmp5 needs to be specified as a child of $tmp4 unless $tmp4 was a termination of $tmp3.... or something like that. I could design the logic to backtrack and do these checks, but it just makes more sense to parse through them one by one.
Re: loop control
by hotshot (Prior) on May 22, 2002 at 14:34 UTC
    It will be usefull if you'll let us see your code. the piece of code you gave seems ok, so probably conditioanl A is never met.

    Thanks.

    Hotshot