44

根据文档while只要表达式为,语句就会执行块。我想知道为什么它会变成一个带有空表达式的无限循环:

while () { # infinite loop
 ...
}

只是文档中的不准确吗?

4

3 回答 3

36
$ perl -MO=Deparse -e 'while () { }'
while (1) {
    ();
}
-e syntax OK

似乎while () {}while (1) {}是等价的。另请注意,在空块中插入了空括号*。

预定义编译器行为的另一个示例:

$ perl -MO=Deparse -e 'while (<>) { }'
while (defined($_ = <ARGV>)) {
    ();
}
-e syntax OK

我会说这只是没有报告特殊情况的文档。

* — 准确地说,stub操作码被插入。它什么都不做,但为enterloop操作码提供一个 goto 目标。没有真正的理由注意到这一点。Deparsestub使用空括号表示此操作,因为括号不生成代码。

于 2012-04-26T12:42:58.853 回答
14

这是Vacuous Truth概念的一个特例。如果没有条件,则条件为真时的陈述本身就是空虚的。

如果我没看错的话,相关的代码似乎在 5.14.1的第 5853 行附近:op.c

5853     if (expr) {
5854         scalar(listop);
5855         o = new_logop(OP_AND, 0, &expr, &listop);
5856         if (o == expr && o->op_type == OP_CONST && !SvTRUE(cSVOPo->op_sv)) {
5857             op_free(expr);              /* oops, it's a while (0) */
5858             op_free((OP*)loop);
5859             return NULL;                /* listop already freed by new_logop */
5860         }
5861         if (listop)
5862             ((LISTOP*)listop)->op_last->op_next =
5863                 (o == listop ? redo : LINKLIST(o));
5864     }
5865     else
5866         o = listop;

I am assuming with no expr in the condition, we reach o = listop. listop was previously defined as listop = op_append_list(OP_LINESEQ, block, cont);.

于 2012-04-26T15:16:29.687 回答
11

这是一个特例。空条件表达式默认为 just true,这意味着“永远循环,或者直到 a break。在 C(和 perl)中,成语

for(;;) {
   // Neverending fun
}

出于相同的原因具有相同的效果。

官方的 perl 文档中似乎没有提到这一点,但是解析器中有一个特殊的规则。也许是因为没有人使用它:)

不过,这个for(;;)成语不太常见。

于 2012-04-26T12:27:23.707 回答