Вопрос по perl, while-loop – Perl: пока без условных

43

Согласнодоктор,while оператор выполняет блок, пока выражениеправда, Интересно, почему это становится бесконечным циклом с пустым выражением:

<code>while () { # infinite loop
 ...
}
</code>

Это просто неточность в документе?

я предпочитаюwhile (1) подчеркнуть намерение. JRFerguson

Ваш Ответ

3   ответа
11

true, что означает «цикл навсегда, или доbreak, В C (и Perl) идиома

for(;;) {
   // Neverending fun
}

имеет тот же эффект по той же причине.

Похоже, что нет никаких упоминаний об этом в официальных документах perl, но в парсере есть специальное правило для этого. Возможно, потому что никто не использует это :)

for(;;) хотя идиома менее необычна.

Это имеет смысл, поскольку if () и till () являются синтаксическими ошибками.
Это где-то задокументировано?
Конечно. Есть некоторые конкретные вещи, определенные как ложные (0, & quot;, undef). Все остальное по умолчанию верно.
это не по умолчанию. Я только что проверил код парсера. Для этого есть специальное правило синтаксического анализа.
Если это так, это, безусловно, нуждается в упоминании в документе.
14

Бессмысленная правда, Если нет условия, заявлениеwhile the condition is true само по себе бессмысленно верно.

Если я читаю это правильно, соответствующий кусок кода, кажется,вокруг линии 5853op.c в 5.14.1:

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);.

Я не думаю, что это так; что o = listop может быть нецикличнымwhile(()) дело.while() фактически реализован в парсере (perly.y); см. правило texpr, которое является либо ничем (в этом случае оно буквально притворяется, что оно увидело «1»), либо выражением expr.
35
$ perl -MO=Deparse -e 'while () { }'
while (1) {
    ();
}
-e syntax OK

while () {} а такжеwhile (1) {} эквивалентны. Также обратите внимание, что пустые символы * вставляются в пустой блок.

Еще один пример предопределенного поведения компилятора:

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

Я бы сказал, что это просто документы, не сообщающие о частном случае.

* & # x2014; Чтобы быть точным,stub Код операции вставлен. Это ничего не делает, но служит цели Goto дляenterloop опкод. Нет никакой реальной причины это замечать. Deparse обозначает этоstub с использованием пустых паренов, поскольку парены не генерируют код.

@briandfoy Да, я заметил, что после публикации этого сообщения ... еще один особый случай. Еще более любопытноfor () это синтаксическая ошибка, ноfor (()) компилируется, но не компилируется вwhile(1) дело, ноforeach $_ (()).
Извините, но ваш пост неверен.1 добавляется Deparse, а не компилятором.while (1) { } а такжеwhile () { } оба компилируются в один и тот же код, поэтому Deparse должен выполнять их разборку одинаково, и он решил отойти к менее запутаннымwhile (1) { }, Если вы посмотрите на фактический код (-MO=Concise), вы увидите, что нет1 добавлено. На самом деле нет никаких условий.1 получаетremoved заwhile (1) { }.
Любопытно,for(;;) уходит какwhile(1) тоже.
@ Brian D Foy, Все изfor (;;) { ... }, while () { ... } а такжеwhile (TRUE) { ... } скомпилировать в цикл без условий (loop { ... }). У Deparse нет возможности узнать, каким был исходный код.
@ TLP Нет, последний имеет смысл.for () У меня есть два синтаксиса, о которых я знаю: стиль C и foreach over list. Так что он не знает, какой вы хотите.for (()) это foreach над пустым массивом:perl -e 'for (()) { print "foo" ;}'

Похожие вопросы