Perl做... while和last命令

sno*_*kin 17 perl

我刚刚遇到一些非常奇怪的行为,我实在无法解释:

do {
    my $qry = $self->getHTMLQuery(undef, $mech->content());
    next if (!defined($qry));

    push(
        @prods,
        map { 'http://www.XXXXYYYX.com'.$_->attr('href') }
            $qry->query('div.prodInfo div.prodInfoBox a.prodLink.GridItemLink')
    );

    $qry->delete();
    $TEST++;

    last if ($TEST >= 10);

} while(eval { $mech->follow_link(class => 'jump next') });

print "WHILE ENDED\n";
Run Code Online (Sandbox Code Playgroud)

上面的代码永远不会打印"WHILE ENDED",即使它$TEST> = 10 时似乎超出了while循环.

但是下面的代码确实打印了"WHILE ENDED":

do {
    my $qry = $self->getHTMLQuery(undef, $mech->content());
    next if (!defined($qry));

    push(
        @prods,
        map { 'http://www.XXXXYYYX.com'.$_->attr('href') }
            $qry->query('div.prodInfo div.prodInfoBox a.prodLink.GridItemLink')
    );

    $qry->delete();
    $TEST++;

} while(eval { $mech->follow_link(class => 'jump next') } && $TEST <= 10);

print "WHILE ENDED\n";
Run Code Online (Sandbox Code Playgroud)

在两个测试中,初始值为$TEST0.

是的行为lastdo...while不同比forwhile {...}

cjm*_*cjm 29

一个do具有循环修改块不就算是真正的循环next,lastredo关注.这在perlsyn中提到过,在那里你会发现Schwern提到的关于用一个裸块围绕它来做last工作的提示.但这不起作用next,因为裸块只执行一次,所以next行为就像last.为了next工作,你可以把裸块do,但随后last会像next.

如果你需要两者nextlast使用a do ... while,最简单的方法是在continue块中使用具有实际条件的无限循环.这两个循环是等价的,除了第二个循环是一个真正的循环,所以它适用于next&last:

do { ... } while condition;
while (1) { ... } continue { last unless condition };
Run Code Online (Sandbox Code Playgroud)


TLP*_*TLP 21

来自perldoc -f last:

"last"不能用于退出返回值的块,例如"eval {}","sub {}"或"do {}"


Sch*_*ern 16

TLP是对的.这个标准的解决方法(我自己就是它)是将do/while包装在一个裸块中,这反过来直观地确实遵循循环控制.

{ do {
    last;
} while 1; }
Run Code Online (Sandbox Code Playgroud)

外面的区块将会被捕获last.如果你想处理next你必须把集团放在里面.

do {{
    next;
}} while 1;
Run Code Online (Sandbox Code Playgroud)

里面的块会抓住next.

不幸的是,你不能两者都做.