Hacker News new | ask | show | jobs
by drostie 4948 days ago
What's very interesting here is the SICP-style recursive looping, combined with the fact that the non-programmer doesn't expect to be able to pass variables but rather expects to make stateful queries. That is, the infrastructure expected (here written in JS) is:

    var query = {};
    function print(x) {
        console.log(x);
        if (typeof x === "number") {
            query = {last_num: x, time_since: 1};
        } else {
            query.time_since += 1;
        }
    }
And given all that, they have invented a fizzbuzz() which, as its last statement in each branch, calls fizzbuzz(). I like the way that it's graphically represented but I also think those semantics are quite interesting.
3 comments

I wouldn't be so quick in concluding that the long back arrow stands for recursive looping. I'd guess it's just a non-coder notation for "and then do that thing again", for which the closest equivalent in actual language would be the `while` loop (most likely infinite, as the author remarked). I don't see the meta-level of considering the algorithm/procedure as a whole here, a one that is needed for thinking in terms of recursive application.

Furthermore, the fact that non-programmer expects to be able to poll the state of everything around (like the numbers which were already printed) would indicate that in their mind, there is no separation between the program/algorithm and the environment it is executed in. (Ironically, this is completely accurate viewpoint if we're thinking at the level of actual machines, be it real ones or abstract models like Turing machines.)

I think the arrows are being though of as GOTO`s.
Inspired by this, I translated the whole solution into JS. I renamed your "query" object to "output_state," which seems like a more accurate name.

    var output_state = {};
    function print(x) {
        console.log(x);
        if (typeof x === "number") {
            output_state = {last_num: x, time_since: 1};
        } else {
            output_state.time_since += 1;
        }
    }

    function fizzbuzz() {
        switch(output_state.last_num) {
            case undefined:
                print(1);
                break;
            default:
                var a = output_state.last_num;
                var b = output_state.time_since;
                var number = a + b;

                if (number % 5 !== 0) {
                    if (number % 3 === 0) {
                        print("Fizz");
                    } else {
                        print(number);
                    }
                } else {
                    if (number % 3 === 0) {
                        print("FizzBuzz");
                    } else {
                        print("Buzz");
                    }
                }
        }

        fizzbuzz();
        // Or, correctly: if (number < 100) { fizzbuzz(); }
    }
I too was struck by the fact that it's essentially an FSM. It's cool that a non-programmer will naturally gravitate towards that structure, while we're forced to spend weeks learning it in upper-level courses...