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
instead. | [reply] [d/l] [select] |
|
|
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. | [reply] [d/l] |
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.
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
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
| [reply] [d/l] |
|
|
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.
| [reply] |
|
|
| [reply] |
|
|
$ perl561 -MO=Deparse -e 'while(1) {1}'
for (;;) {
'???';
}
| [reply] [d/l] [select] |
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...
| [reply] [d/l] |
|
|
It is quite interesting to see that sometimes mistyping can lead to unexpected discoveries in the language syntax...
Mind
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.
| [reply] |
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 (;;). | [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |
|
|
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'
| [reply] [d/l] [select] |
|
|
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.
| [reply] [d/l] [select] |