Perl: while with no conditional

前端 未结 3 1451
不知归路
不知归路 2021-02-01 13:16

According to the doc, the while statement executes the block as long as the expression is true. I wonder why it becomes an infinite loop with an empty expression:

相关标签:
3条回答
  • 2021-02-01 13:48

    This is a special case. An empty condition expression defaults to just true, which means "loop forever, or until a break. In C (and perl) the idiom

    for(;;) {
       // Neverending fun
    }
    

    has the same effect for the same reason.

    There doesn't appear to be any mention of this in the official perl docs, and yet there is a special rule in the parser for it. Perhaps it's because nobody uses it :)

    The for(;;) idiom is less uncommon though.

    0 讨论(0)
  • 2021-02-01 13:56

    This is a special case of the concept of Vacuous Truth. If there is no condition, the statement while the condition is true is itself vacuously true.

    If I am reading this correctly, the relevant piece of code seems to be around line 5853 of op.c in 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;
    

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

    0 讨论(0)
  • 2021-02-01 14:08
    $ perl -MO=Deparse -e 'while () { }'
    while (1) {
        ();
    }
    -e syntax OK
    

    It seems that while () {} and while (1) {} are equivalent. Also note that empty parens* are inserted in the empty block.

    Another example of pre-defined compiler behaviour:

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

    I would say that this is just the docs not reporting a special case.

    * — To be precise, the stub opcode is inserted. It does nothing, but serves a goto target for the enterloop opcode. There's no real reason to note this. Deparse denotes this stub op using empty parens, since parens don't generate code.

    0 讨论(0)
提交回复
热议问题