tangentially, can somebody point me to what are considered the best fizzbuzz solutions? I'm both an experienced and cs-educated coder, and I know what I would consider to be a good solution, but I have no idea what the rest of "you" are looking for. (my favored solution would be a small number of state machines running in parallel to sieve-of-eratosthenes the correct answers thus avoid innumerable divisions, but maybe that's just me and I'm old fashioned?)
Re:GOTOphobia Considered Harmful (In C)
by anonymoushn on Sunday February 26, 2023 @11:43PM
(#34953059)
Surely your compiler won't actually emit an integer modulus if you tell it to mod by a constant?
I don't claim to have the best, or even good, fizzbuzz implementations, but if you're looking for a lot of fizzbuzz implementations:
Re:GOTOphobia Considered Harmful (In C)
by zozbot234 on Sunday February 26, 2023 @08:10PM
(#34951748)
The loop you posted is a do-while loop; the while loop has a somewhat less intuitive translation to GOTO:
loop_test: IF (NOT loop_condition) GOTO after_loop
loop_body
GOTO loop_test
after_loop: etc...Not too far from assembly ...
Almost, except in assembly, we always have a call stack. So even assembly is a procedural language, even though it doesn't otherwise have structured control flow.
Could be worse.
https://github.com/Keith-S-Thompson/fizzbuzz-c/blob/master/f...
#include <stdio.h>
#include <setjmp.h>
int main(void) {
jmp_buf jb[7];
volatile int j = 0;
setjmp(jb[0]);
volatile int i = 1;
if (j == 0) setjmp(jb[1]);
if (j == 1 && i > 100) longjmp(jb[6], 0);
if (j == 1 && i % 15 == 0) longjmp(jb[4], 0);
if (j == 1 && i % 3 == 0) longjmp(jb[2], 0);
if (j == 1 && i % 5 == 0) longjmp(jb[3], 0);
if (j == 1) printf("%d\n", i);
if (j == 1) longjmp(jb[5], 0);
if (j == 0) setjmp(jb[2]);
if (j == 1) puts("Fizz");
if (j == 1) longjmp(jb[5], 0);
if (j == 0) setjmp(jb[3]);
if (j == 1) puts("Buzz");
if (j == 1) longjmp(jb[5], 0);
if (j == 0) setjmp(jb[4]);
if (j == 1) puts("FizzBuzz");
if (j == 0) setjmp(jb[5]);
i ++;
if (j == 1) longjmp(jb[1], 0);
if (j == 0) setjmp(jb[6]);
j ++;
if (j < 2) longjmp(jb[0], 0);
}I am sobbing in pain at that atrocity.
I live to serve.
Procedural or not was more of a spectrum. If you look at early BASICs, for example, they had GOSUB, and it could recurse, so there was a return-address stack. But GOSUB did not have any provisions to pass arguments or return values - it was just a GOTO that remembered where it came from; you had to use globals to pass data around. So if you wanted a data stack (i.e. locals), you had to rig your own with arrays.
OTOH early FORTRAN had procedures with arguments and results, but no recursion.
Structural or not was also not necessarily all-in. FORTRAN and BASIC both had for-loops before they had structured conditionals.
Loops would look like:
Fizzbuzz would look something like: Often, this wasn't just constrained to a single function; the whole program would be constructed like this, with gotos which jump back and forth across pages and pages of code. Languages wouldn't even have a call stack with subroutines (which is why "procedural" languages -- languages with procedures -- were important enough to be given a special name).At least that's my understanding of it. I haven't lived through this, and my only experience with this kind of stuff is writing assembly, where we always make use of a call stack, so even that is in practice a procedural language. If I have gotten anything wrong, please correct me.