web-dev-qa-db-ja.com

Perl:条件なしで

doc によると、式が true である限り、whileステートメントはブロックを実行します。空の式で無限ループになるのはなぜでしょうか。

while () { # infinite loop
 ...
}

それは単にドキュメントが不正確なのですか?

44
Eugene Yarmash
_$ 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ターゲットを提供します。これに注意する本当の理由はありません。括弧はコードを生成しないため、Deparseは空の括弧を使用してこのstub opを示します。

36
TLP

これは Vacuous Truth の概念の特別なケースです。条件がない場合、ステートメントがである一方で、条件がtrueであると、それ自体が空虚にtrueになります。

これを正しく読んでいる場合、関連するコードは 5.14.1の_op.c_ の5853行目です:

_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;
_

条件にexprがないと仮定すると、_o = listop_に到達します。 listopは、以前はlistop = op_append_list(OP_LINESEQ, block, cont);として定義されていました。

14
Sinan Ünür

これは特殊なケースです。空の条件式は、デフォルトでtrueのみに設定されます。これは、「永久にループするか、またはbreakまでループすることを意味します。C(およびPerl)では、イディオム

_for(;;) {
   // Neverending fun
}
_

同じ理由で同じ効果があります。

公式のPerlドキュメントにはこれについての言及はないようですが、パーサーにはそのための特別なルールがあります。多分それはだれもそれを使用していないからです:)

for(;;)イディオムはそれほど珍しくありません。

11
Michael Slade