Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"

backwards if and while looping

by jcpunk (Friar)
on Oct 01, 2004 at 19:47 UTC ( #395723=perlquestion: print w/replies, xml ) Need Help??

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

Greetings ye who may help me (and merely a hello to those who may not)
I've been fiddeling around with a program and got it down to roughly
if ( not $error ) { while ($a < $b) { $a++; } }
I was thinking, that if looks kinda nasty, so I went for
while ($a < $b) if not $error { $a++; }
As I find that to look much better, but I get the following error message telling me that this does not work.
syntax error at line 62, near ") if" Global symbol "%error" requires explicit package name at line 63. syntax error at line 69, near "}"
So, am I stuck with that rather ugly looking set of lines or is there a more beautiful replacement than
if ( not $error ) { while ($a < $b) { $a++; }}

all code is tested, and doesn't work so there :p (varient on common PM sig for my own ammusment)

Replies are listed 'Best First'.
Re: backwards if and while looping
by Grygonos (Chaplain) on Oct 01, 2004 at 19:51 UTC

    Putting it on one line will illuminate the problem. while ($a < $b) if not $error{$a++}; It thinks error is a hash since immediately following it (and owe to perls ignoring whitespaces) is a opening curly a var and a closing curly.. effectively referencing the $a+1 key of the hash %error.

    personally I don't see a better way than

    if(!$error) { while($a < $b) { $a++; } }

Re: backwards if and while looping
by blokhead (Monsignor) on Oct 01, 2004 at 20:35 UTC
    I'm surprised no one has suggested this (I'll also assume your simple $a++ in the loop is just for demonstration purposes):
    while (not $error and $a < $b) { $a++; }


      this will test $error in every instance of the loop, as opposed to only once before initiating the loop. it works, but it requires more cpu time...
Re: backwards if and while looping
by ikegami (Pope) on Oct 01, 2004 at 20:40 UTC

    Some other alternatives not yet mentioned:

    while (not $error and $a < $b) { $a++; }


    do { while ($a < $b) { $a++; } } if (not $error);


    do { $a++ while ($a < $b); } if (not $error);
Re: backwards if and while looping
by periapt (Hermit) on Oct 01, 2004 at 19:55 UTC
    The line
    while ($a < $b) if not $error { $a++; }
    is more clearly interpreted by perl to be  while ($a < $b) if not $error{ $a++; }. Perl thinks $error{ $a++ } is a hash reference to %error. A construct that would DWYM would be (parenthesis not strictly necessary)
    (!$error) && ($a++ while ($a < $b))

    use strict; use warnings; use diagnostics; (if needed)
      My dumbed down example seems to not be as excellent as I initially thought.....
      (!$error) && (print "$data" while ($data = <input>))
      is erroring out on me with the print... Is this a fatal flaw in my plan?

      all code is tested, and doesn't work so there :p (varient on common PM sig for my own ammusment)
        $error or print $data while $data = <input>;

        Examine what is said, not who speaks.
        "Efficiency is intelligent laziness." -David Dunham
        "Think for yourself!" - Abigail
        "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon
Re: backwards if and while looping
by cLive ;-) (Prior) on Oct 01, 2004 at 19:58 UTC
    Not really sure what you're trying to do, but 1) avoid $a and $b outside of sort subs and 2) if $a and $b are integers, you can simplify to:
    $error or $a = $a < $b ? $b : $a;
    cLive ;-)
Re: backwards if and while looping
by !1 (Hermit) on Oct 01, 2004 at 22:16 UTC

    For all of these "why not" people, why not just do:

    $a = $b unless $error;

    I know it doesn't work correctly if $a > $b. In my defense, some of the other solutions don't either. Anyway,

    while ($a < $b) if not $error { $a++; }

    looks pretty disgusting if you ask me. Whereas

    $a++ while ! $error && $a < $b; if ( ! $error ) { $a++ while $a < $b; } do { $a++ while $a < $b } if ! $error;

    all look a bit more elegant. Also

    $a++ while not $error || $a >= $b; $a = $b unless $error or $a >= $b;

    are cool, IMHO.

      There's another case to account for... if $a or $b isn't integer, and their fractional parts differ (i.e. ($a - int $a) != ($b - int $b)) and $a < $b, then

      $a = $b unless $error or $a >= $b;

      (or similar examples in the thread) has a different result than the OP's code.

      I think it muddies the water to test $error every time through the loop, as some of these solutions do, when you only need to test it once. If $a or $b might be non-integer, here's one way to do it:

      if ($a < $b and !$error) { $a = int $b + ($a - int $a); $a++ if $a < $b; }

      I left out doing the floating point comparisons correctly...

      Updated: Fixed a dumb error in the code.

        Yeah, but who uses real numbers? ;-P
Re: backwards if and while looping
by johnnywang (Priest) on Oct 01, 2004 at 19:56 UTC
    while ($a < $b) if not $error { $a++; }
    is the same as
    while ($a < $b) if not $error{ $a++; }
    so the parser thinks you are asking for %error with key "$a++;".

    Why not:

    (not $error) and $a = $b;
Re: backwards if and while looping
by talexb (Canon) on Oct 01, 2004 at 21:39 UTC

    Sorry, have I missed something? .. Can't you just write

    if ( not $error ) { $a = $b }
    and be done with it? Why do you have to increment $a up to $b until they're equal?

    Alex / talexb / Toronto

    "Groklaw is the open-source mentality applied to legal research" ~ Linus Torvalds

Log In?

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

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (1)
As of 2021-10-19 00:08 GMT
Find Nodes?
    Voting Booth?
    My first memorable Perl project was:

    Results (76 votes). Check out past polls.