SPUG: "last" behaving oddly in -n loop

Tim Maher tim at consultix-inc.com
Wed Aug 20 15:55:09 CDT 2003


SPUGsters,

I'm confused about how "last" is being handled with a -n
(implicit) loop, which is very different from the way "next"
is being handled.  I'd appreciate any insights!

Here's the problem in a nutshell:

$ cat last2
print "$.: $ARGV" and last LINE ; END{print "File is $ARGV\n"}

$ perl -wln last2 motd1 motd2
1: motd1
File is motd1
$

Why didn't it process the second file, motd2, as happens with "next"?
It's acting like last is magically allowed to break out of the outer
(invisible) foreach loop, while next only affects the inner (invisible)
while loop.

Deparsings and more details are shown below.

-Tim
==============================================================
| Tim Maher, Ph.D.                    tim(AT)teachmeperl.com | 
| SPUG Founder & Leader              spug(AT)seattleperl.com |
| Seattle Perl Users Group        http://www.seattleperl.com |
| SPUG Wiki Site               http://spugwiki.perlocity.org |
| Perl Certification Site      http://perlcert.perlocity.org |
==============================================================

tim at timji:/tmp> cat next2
print "$.: $ARGV" and next LINE ; END{print "File is $ARGV\n"}
tim at timji:/tmp> perl -wln next2 motd1 motd2
1: motd1
2: motd1
3: motd1
4: motd1
5: motd2
6: motd2
7: motd2
8: motd2
File is motd2

tim at timji:/tmp> perl -MO=Deparse -wln next2 motd1 motd2
BEGIN { $^W = 1; }
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    next LINE if print "$.: $ARGV";
    sub END {
        print "File is $ARGV\n";
    }
    ;
}
The outer-loop stuff ( presumably, @ARGV or @ARGV='-';
foreach $ARGV (@ARGV) {} ) is not shown, but because it works
correctly, I don't mind 8-}

But after seeing the following, I mind!

tim at timji:/tmp> cat last2
print "$.: $ARGV" and last LINE ; END{print "File is $ARGV\n"}

tim at timji:/tmp> perl -MO=Deparse last2 motd1 motd2
BEGIN { $^W = 1; }
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
    chomp $_;
    last LINE if print "$.: $ARGV";
    sub END {
        print "File is $ARGV\n";
    }
    ;
}

tim at timji:/tmp> perl -wln last2 motd1 motd2
1: motd1
File is motd1
$

Why didn't it go on to the next file, after last-ing out of the
loop for the first one? I.e., if "next LINE" triggers the next
iteration (which would have happened anyway), and allows the
filename args to get processed in sequence, why doesn't "last
LINE" just terminate the "inner" loop, and allow the (invisible)
outer loop to open the next file? "close ARGV" *does* work that
way, but it also resets $., which I don't want, and in any case
I'd rather have "last LINE" do what I think it should!

Any ideas?

-Tim
*------------------------------------------------------------*
| Tim Maher (206) 781-UNIX  (866) DOC-PERL  (866) DOC-UNIX   |
| tim(AT)Consultix-Inc.Com  TeachMeUnix.Com  TeachMePerl.Com |
*+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-*
|  Watch for my Book: "Minimal Perl for Shell Programmers"   |
*------------------------------------------------------------*



More information about the spug-list mailing list