in reply to while loop acting up, though I'm not sure how

You can see what's going on by minimally changing your code, like this:
use strict; use warnings; my $expiry = time + 3600; my $time; my $previoustime; sub mysleep { printf 'before sleeping: time = %d, $time = %d, %s', time, $time +, "\n"; sleep shift; printf 'after sleeping: time = %d, $time = %d, %s', time, $time +, "\n"; } while ( $time = time and $time + 300 < $expiry and ( $time - $previoustime >= 10 or mysleep (10 + $previoustime - $time) ) ) { $previoustime = $time; warn $time; }

Replies are listed 'Best First'.
Re^2: while loop acting up, though I'm not sure how
by msh210 (Monk) on Nov 17, 2015 at 15:27 UTC

    That adds information, but I still don't see the bug. The output is

    Use of uninitialized value $previoustime in subtraction (-) at soonix. +pl line 15. 1447773471 at MWE.pl line 22. before sleeping: time = 1447773471, $time = 1447773471, after sleeping: time = 1447773481, $time = 1447773471, 1447773471 at MWE.pl line 22. 1447773481 at MWE.pl line 22. before sleeping: time = 1447773481, $time = 1447773481, after sleeping: time = 1447773491, $time = 1447773481, 1447773481 at MWE.pl line 22. 1447773491 at MWE.pl line 22. before sleeping: time = 1447773491, $time = 1447773491, after sleeping: time = 1447773501, $time = 1447773491, 1447773491 at MWE.pl line 22. 1447773501 at MWE.pl line 22.

    etc. The reason for the second warn each time around is (presumably) because mysleep doesn't get called i.e. because !($time - $previoustime >= 10) i.e. (presumably) because $time - 10 < $previoustime. But that's not the case: after all, we've set $previoustime = $time (which we were just warned is time - 10) and then $time = time. So I still don't get what's going on.

      • The first time, $previoustime is undefined (warning from "line 15"), hence ($time - $previoustime >= 10) is true and the rest of the or is ignored (first "line 22" warning), because the loop condition is true anyway.
      • Second time the condition is evaluated: Since in the previous iteration the condition was true without sleep, the time assignment happened within the same second as the previous one, resulting in a sleep 10
      • Third time: After the sleep, time has advanced by 10 seconds, ($time - $previoustime >= 10) being true again, same situation as in first iteration, i.e. no sleep.
      • Fourth iteration is just like the second
      The sleep is not evaluated (hence, not executed) every odd iteration because of the "short-circuit" nature of perl's boolean operators. davido explains this thoroughly in Perl Idioms Explained - && and || "Short Circuit" operators - despite the subject, this is also regarding and and or.
        Thank you.