const deadline = ...;
while (true) {
if (try readMailboxIn(...)) |in_content| return in_content;
if (try ...now(...).compare(.gte,deadline)) return error.MailboxTimeout;
}
Maybe thereās something fancier you can do with Io (go-like select?) to return the first of two async tasks (either readMailboxIn or sleep(mailbox_timeout), whichever finishes first), but if Iām only allowed to change this one function then ^thatās what Iād do.
Something that makes me uneasy about this code is the potential for me to somehow introduce a bug in the future that would cause this to never return. The while (true) is scary.
This issue is that a short deadline my cause a return before readMailboxIn can execute at least once. I would like the semantics of this function to always execute readMailboxIn at least once (in the absence of errors).
FWIW I sometimes use a ārunningā variable for this, e.g. smth like:
var running = true;
while (running) {
// on exit condition set running to false
}
ā¦sometimes thatās better than various breaks in the middle of the while-body when you want to make sure that the entire while body is executed even on the last iteration.
I actually miss do-while a bit What I do miss in Cās do-while is that the lifetime of variables declared inside the while-body are not extended into the while-condition-check (e.g. sort of a reverse for (int iā¦);
This method is better and more refactoring-proof than putting the conditional break at the bottom of the loop body, not only because it prevents the break from getting lost in the sauce but also because continue statements wonāt inadvertently skip over it.
This is a good trick to know. However, in this case you donāt need it. The compiler will complain if the loop is able to finish without a return, and there is no return statement after the loop. That will cause void to be implicitly returned, and void is not the return type of the function.
While Iām in no position to be questioning Andrewās advice, given that āAll loops must have a fixed upper-boundā is #2 on NASAs list of rules for safety critical code, I think a healthy trepidation of while (true) is not a terrible thing. source
Yeah, I think sometimes people underestimate how good a do-while-loop can express the intent of the programmer compared to workarounds.
I still dislike that certain languages donāt have it for that very reason (although that doesnāt mean that I always have a clue how to include it in all of them, like for example Python).
I normally either put the loop body into a separate body, or (if the code is short enough) just duplicate it (and create comments that tells the programmer that).
Neither is ideal (the first because it makes you jump around the code and because of parameter passing; the second because it not really obvious from reading the code).
Some additional context, Iām semi-confident that I will be refactoring this later to use a *std.Io.Writer as an out parameter instead of returning InContent (passing about 1500 bytes on the the stack). In that case the return value will change to !void.
No function should be longer than what can be printed on a single sheet of
paper in a standard reference format with one line per statement and one line per
declaration. Typically, this means no more than about 60 lines of code per function.
I think this an extremely goofy suggestion that is backed up neither by evidence nor sound reasoning.
Zig compiler source code for example would be a lot more convoluted if it followed this suggestion.
I doubt even TigerBeetle follows this crazy advice.
Letās take a peek! In 20 seconds I cracked open src/vsr/replica.zig and found the open function which is 277 lines long.