Computer Things

Subscribe
Archives
November 24, 2025

One more week to the Logic for Programmers Food Drive

Also: COBOL is a bad language

A couple of weeks ago I started a fundraiser for the Greater Chicago Food Depository: get Logic for Programmers 50% off and all the royalties will go to charity.1 Since then, we've raised a bit over $1600. Y'all are great!

The fundraiser is going on until the end of November, so you still have one more week to get the book real cheap.

I feel a bit weird about doing two newsletter adverts without raw content, so here's a teaser from a old project I really need to get back to. Notes on structured concurrency argues that old languages had a "old-testament fire-and-brimstone goto" that could send control flow anywhere, like from the body of one function into the body of another function. This "wild goto", the article claims, what Dijkstra was railing against in Go To Statement Considered Harmful, and that modern goto statements are much more limited, "tame" if you will, and wouldn't invoke Dijkstra's ire.

I've shared this historical fact about Dijkstra many times, but recently two separate people have told me it doesn't makes sense: Dijkstra used ALGOL-60, which already had tame gotos. All of the problems he raises with goto hold even for tame ones, none are exclusive to wild gotos. So

This got me looking to see which languages, if any, ever had the wild goto. I define this as any goto which lets you jump from outside to into a loop or function scope. Turns out, FORTRAN had tame gotos from the start, BASIC has wild gotos, and COBOL is a nonsense language intentionally designed to horrify me. I mean, look at this:

The COBOL ALTER statement, which redefines a goto target

The COBOL ALTER statement changes a goto's target at runtime.

(Early COBOL has tame gotos but only on a technicality: there are no nested scopes in COBOL so no jumping from outside and into a nested scope.)

Anyway I need to write up the full story (and complain about COBOL more) but this is pretty neat! Reminder, fundraiser here. Let's get it to 2k.


  1. Royalties are 80% so if you already have the book you get a bit more bang for your buck by donating to the GCFD directly ↩

If you're reading this on the web, you can subscribe here. Updates are once a week. My main website is here.

My new book, Logic for Programmers, is now in early access! Get it here.

Don't miss what's next. Subscribe to Computer Things:
Join the discussion:
YawarRaza7349
November 25, 2025, morning

Actually, that ALTER statement seems fine. Notice that the "body" of paragraph-name-1 can only be a single GO statement. That means that paragraph-name-1 is effectively a name for some other GO destination. Without ALTER, it would be an alias for said destination, but with ALTER, it's instead a mutable variable that can reference an arbitrary GO destination. This can be handy for emulating what you might otherwise do with a first-class function. See the following C/JS examples:

Click to expand C code

#include <stdio.h>

int (*summand)(int);
int summate(int l, int u) {
    int sum = 0;
    for (int i = l; i <= u; ++i) {
        sum += (*summand)(i);
    }
    return sum;
}

int id(int i) { return i; }
int sqr(int i) { return i * i; }

int main() {
    summand = &id;
    printf("%d = %d\n", summate(1, 10), 11 * 10 / 2);
    summand = &sqr;
    printf("%d = %d\n", summate(1, 10), 21 * 11 * 10 / 6);
    return 0;
}
Click to expand JS code

let summand;
const summate = (l, u) => {
    let sum = 0;
    for (let i = l; i <= u; ++i) {
        sum += summand(i);
    }
    return sum;
};

const id = x => x;
const sqr = x => x * x;

summand = id;
console.log("" + summate(1, 10) + " = " + (11 * 10 / 2));
summand = sqr;
console.log("" + summate(1, 10) + " = " + (21 * 11 * 10 / 6));

In COBOL, you'd define summand as a paragraph with a "body" of a single GO statement. The above assignments to summand would then each translate to an ALTER statement in COBOL: ALTER summand TO PROCEED TO id, ALTER summand TO PROCEED TO sqr (or something like that; I don't know COBOL). Of course, that GO(TO) doesn't return means you can't as easily reuse id and sqr (they need to GO back to summate), but that sounds orthogonal to taking issue with ALTER as compared to normal GO(TO).

Reply Report
Powered by Buttondown, the easiest way to start and grow your newsletter.