Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

while ()

by blazar (Canon)
on Jun 07, 2005 at 16:20 UTC ( #464367=perlquestion: print w/replies, xml ) Need Help??

blazar has asked for the wisdom of the Perl Monks concerning the following question:

Basically this is a question raised by calin at Re^3: Reopen file when contents changed?, as a cmt to my own Re^2: Reopen file when contents changed?.

In short it seems that while () is interpreted much like while (1) (but please refer to the above mentioned node) which seems slightly counterintuitive and seems not to be documented.

Any {explanation,cmt}?

Replies are listed 'Best First'.
Re: while ()
by ysth (Canon) on Jun 07, 2005 at 19:40 UTC
    This isn't related to being able to transform for into while, and appears to be a deliberate choice. The parser injects a constant "1" if either while() or the middle part of for(;;) are empty: perly.y:
    /* Loops: while, until, for, and a bare block */ loop : label WHILE '(' remember texpr ')' mintro mblock cont { PL_copline = (line_t)$2; $$ = block_end($4, newSTATEOP(0, $1, newWHILEOP(0, 1, (LOOP*)Nullop, $2, $5, $8, $9, $7))); + } ... | label FOR '(' remember mnexpr ';' texpr ';' mintro mne +xpr ')' mblock /* basically fake up an initialize-while lines +eq */ { OP *forop; PL_copline = (line_t)$2; forop = newSTATEOP(0, $1, newWHILEOP(0, 1, (LOOP*)Nu +llop, $2, scalar($7), $12, $10, $9)); if ($5) { forop = append_elem(OP_LINESEQ, newSTATEOP(0, ($1?savepv($1):N +ullch), $5), forop); } $$ = block_end($4, forop); } ... /* Boolean expression */ texpr : /* NULL means true */ { (void)scan_num("1", &yylval); $$ = yylval.op +val; } | expr ;
    ("remember" starts a lexical scope, but doesn't use any tokens.)

    AIUI, while () would be illegal if it had said

    loop : label WHILE '(' remember expr ')' mintro mblock cont
      The code in ysth's post is completely definitive, of course, and can be further verified by using the Perl bytecode compiler (B::Bytecode). If you execute the following:
      perl -MO=Bytecode,-H,-ofor_loop -e 'for (;;) {}' perl -MO=Bytecode,-H,-owhile_loop -e 'while () {}' perl -MO=Bytecode,-H,-owhile1_loop -e 'while (1) {}'
      and then diff the resulting files (for_loop, while_loop and while1_loop), you will find that they are all completely identical. This means that all three are exactly equivalent as far as code execution goes.
Re: while ()
by Roy Johnson (Monsignor) on Jun 07, 2005 at 16:52 UTC
    Very interesting. A special-case idiom that never caught on (people still use while(1)). Note that it is a very special case of there being no expression. while(()) and while(do{}) never loop. And you can't mimic the behavior in predicate while, because the parentheses are optional: ... while; is a syntax error, and ... while (); is the same as ... while (());

    Update: I didn't mean it's a very special case out of the set of cases where there is no expression; I meant that there being no expression is a very special case (that you can't mimic with any expression). The documentation specifies that while takes an expression.

    Caution: Contents may have been coded under pressure.
      I don't believe that while(()) is an example of no expression. Rather, while(()) evaluates the condition (), a list of no elements. A list evaluated in scalar conext yields the last element, according to man perldata:
      If you evaluate an array in scalar context, it returns the length of the array. (Note that this is not true of lists, which return the last value, like the C comma operator, nor of built-in functions, which return whatever they feel like returning.)
      What's the "last value" of an empty list? Experiments indicate that it's undef, a false value, so the while-loop doesn't loop.
Re: while ()
by Joost (Canon) on Jun 07, 2005 at 16:39 UTC
    I've never used this construct myself, and tt does seem unintuitive and contrary to perlsynL: "The "while" statement executes the block as long as the expression is true (does not evaluate to the null string "" or 0 or "0"). ".

    FYI, the output of deparse (which gets it wrong, occasionally) is:

    > perl -MO=Deparse -e 'while () { print "..\n" }' while (1) { print "..\n"; } -e syntax OK

      It's not contrary to that quote from perlsyn, because there is no expression to evaluate. That quote simply doesn't apply.

      However, it is contrary to the perlsyn line that says "LABEL while (EXPR) BLOCK", without adding that EXPR is optional.

        I now think that while () deparses as for because while (1) is "optimised" (whatever that means) into for(;;) in perl 5.6.1.

        $ perl561 -MO=Deparse -e 'while(1) {1}' for (;;) { '???'; }
Re: while ()
by bofh_of_oz (Hermit) on Jun 07, 2005 at 17:06 UTC
    I intended to use while (1), honest! <grin>

    It is quite interesting to see that sometimes mistyping can lead to unexpected discoveries in the language syntax...

    Surprisingly, I couldn't find anything about this syntax in Perl or C on the Net... But from (working, heh) code, it seems that an empty condition is evaluated as true...

    Here's what I found that might be related. It's from description of perl5db, the Perl debugger:

    ... %postponed Saves breakpoints for code that hasn't been compiled yet. Keys are sub +routine names, values are: * compile - break when this sub is compiled * break +0 if <condition> - break (conditionally) at the start of +this routine. The condition will be '1' if no condition was specified +. ...

    An idea is not responsible for the people who believe in it...

      It is quite interesting to see that sometimes mistyping can lead to unexpected discoveries in the language syntax...


      Richard Wilbur

      Mind in its purest play is like some bat
      That beats about in caverns all alone,
      Contriving by a kind of senseless wit
      Not to conclude against a wall of stone.

      It has no need to falter or explore;
      Darkly it knows what obstacles are there,
      And so may wave and flitter, dip and soar
      In perfect courses through the blackest air.

      And has this simile a like perfection?
      The mind is like a bat. Precisely. Save
      That in the very happiest intellection
      A graceful error may correct the cave.

Re: while ()
by ikegami (Patriarch) on Jun 07, 2005 at 16:30 UTC
    It might be related to for (;;) being interpreted as while (1). This parallel's C's behaviour for for (;;).
      I think so too. However perlsyn suggest that it is C-style for which is really a while loop in disguise and not the other way round.

        If for is really a while in disguise, maybe they allowed while to have a empty condition to create a simple transformation from for to while.

        In other words, if

        for (a; b; c) { d }

        is translated into

        a; while (b) { d } continue { c }

        having the while accept an empty condition simplifies the translation.

        By the way, C doesn't allow an empty while condition:
        a.cpp:5: ANSI C++ forbids an empty condition for `while'

      I agree. The phenomenon that for in perl is equivalent to while is best shown in that for(;<>;){ has the same magic as while(<>){.

      Also I note that until(){ is accepted too, and it seems to mean until(1){, that is, it's not executed at all.

      Of course, while() means while(1) only as a prefix while. A suffix while (); has an empty list in its condition as expected, so it doesn't execute at all, a suffix while; is an error, and the results for until is similar.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://464367]
Approved by Joost
Front-paged by tlm
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others musing on the Monastery: (5)
As of 2022-08-08 09:45 GMT
Find Nodes?
    Voting Booth?

    No recent polls found