http://qs321.pair.com?node_id=676036

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

Just stumbled over this strange distinction:
do {$i++} until ($i==$x);
evaluates the statement before checking the condition, but
$i++ until ($i==$x);
checks the condition first.

I find the second example quite surprising and the opposite of DWIM. And the inconsistency makes it even worse. Ok, postfix loop constructs shouldn't be used according to 'Perl Best Practices' for other reasons anyway. This is just one more reason.

But my restless mind wants to know: Why is that so? Just historical bagagge or is there some hidden justification for this?

Replies are listed 'Best First'.
Re: do {$i++} until vs. $i++ until
by Fletch (Bishop) on Mar 25, 2008 at 04:04 UTC

    It's consistent and orthogonal with the same construct in C. Think of it more of a syntactic construct along the lines of while( EXPR ) BLOCK continue BLOCK rather than an EXPR until EXPR where the first EXPR is a do BLOCK.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Note that I did not criticize the first-execute-then-check do{} until but the first-check-then-execute of $i++ until. THAT is the code that feels wrong. That is the construct that puzzles me. Anyone know a language where this is handled the same?

      But I could live with the "wrong" construction if both cases were at least consistent with each other.

Re: do {$i++} until vs. $i++ until
by Anonymous Monk on Mar 25, 2008 at 04:13 UTC

    This is documented in perlsyn:

    The while and until modifiers have the usual "while loop" semantics (conditional evaluated first), except when applied to a do-BLOCK (or to the deprecated do-SUBROUTINE statement), in which case the block executes once before the conditional is evaluated. This is so that you can write loops like:
    do { $line = <STDIN>; ... } until $line eq ".\n";

      The disadvantage of that idiom is that the scope of $line must extend outside the block where is it used. Declaring $line inside the block results in a syntax error

      use strict; do { my $line = <STDIN>; ... } until $line eq ".\n"; # Syntax error __END__ Global symbol "$line" requires explicit package name
      unlike a while(condition) {} the condition is not in the same scope as the block. It can be written as
      use strict; INPUT: while ( my $line = <STDIN> ) { last INPUT if $line eq ".\n"; ... }
      which will restrict $line to the while block

      Update: Code updated

        Those two snippets aren't equivalent. Aside from the fact that the latter also exits if <STDIN> returned undef, you reversed the order of the loop body (...) and the exit condition (last INPUT if $line eq ".\n";)

Re: do {$i++} until vs. $i++ until
by wade (Pilgrim) on Mar 25, 2008 at 04:49 UTC
    For what it's worth, 'Perl Best Practices' isn't so hot on until statements, either (though I find your, specific, examples pretty easy to read). 8o)
    --
    Wade
      Conway's main critizism isn't readability (the methods of avoiding it diminish readability as much as the do-loop IMHO).

      The main problem he sees is that the do-loop isn't a real loop, so that 'next','last' statements are not working as expected. He is absolutely right, but I still use do-loops sometimes, especially in small loops where the rewrite would blow up the loop significantly.