Preferences

I got to being about 25% as productive in Forth as in C once I learned to stop trying to use the stack for local variables. Maybe with enough practice I might get to being as productive as in C, or even more so. I doubt I'd get to being as productive as in Python, which I think is about 3× as productive as C for me.

I think that if I were, say, trying to get some piece of buggy hardware working, so that most of the complexity of my system was poking various I/O ports and memory locations to see what happened, Forth would already be more productive than C for me. Similar to what Yossi Kreinin said about Tcl:

https://yosefk.com/blog/i-cant-believe-im-praising-tcl.html

Tcl is also good for that kind of thing, but Tcl is 1.2 megabytes, and Forth is 4 kilobytes. You can run Forth on computers that are two orders of magnitude too small for Tcl.

So I think we shouldn't evaluate Forth as a programming language. We should think of it as an embedded operating system. It has a command prompt, multitasking, virtual memory, an inspector for variables (and arbitrary memory locations), and a sort of debugger: at any time, at the command prompt, you can type the name of any line of code to execute it and see what the effect is, so you can sort of step through a program by typing the names of its lines in order. Like Tcl and bash, you can also program in its command-prompt language, and in fact build quite big systems that way, but the language isn't really its strength.

But there is an awful lot of software out there that doesn't really need much complicated logic: some data, some transformations, and maybe some API calls to make to some motors or sensors (or an application and a database). So it doesn't really matter if you're using a weak language like Tcl or Forth because the program logic isn't the hard part of what you're doing.

And it's in that spirit that Frank Sergeant's "three instruction Forth" isn't a programming language at all; it's a 66-byte monitor program that gives you PEEK, POKE, and CALL.

https://pages.cs.wisc.edu/~bolo/shipyard/3ins4th.html

On the other hand, if the computer you're programming has megabytes of RAM rather than kilobytes, and megabits of bandwidth to your face rather than kilobits, you can probably do better than Forth. You can get more powerful forms of what Rusher is calling "liveness" than Forth's interactive procedure definition and testing at the command prompt and textual inspection of variables and other memory locations on demand; you can plot metrics over time and record performance traces for later evaluation. You can afford infix syntax, array bounds checking (at least most of the time), and dynamic type checking.


jdougan
I always find this [1] article to be the most trenchant regarding Forth:

> "Forth is about the freedom to change the language, the compiler, the OS or even the hardware design".

> …And the freedom to change the problem.

In my employed work life it has been fairly rare that I can make more than tiny changes to the problem, making Forth not useful.

[1] https://yosefk.com/blog/my-history-with-forth-stack-machines...

kragen OP
Well, Yossi is probably a better programmer than I am, but I think I'm probably better at Forth than he was, and I think he was Doing It Wrong. And he sort of admits this: he was doing big-bang compilation rather than poking interactively at the hardware, he left out all the metaprogramming stuff, and he was trying to use the stack for local variables because he designed the hardware with a two-cycle memory fetch and no registers for local variables:

    : mean_std ( sum2 sum inv_len -- mean std )
      \ precise_mean = sum * inv_len;
      tuck u* \ sum2 inv_len precise_mean
      \ mean = precise_mean >> FRAC;
      dup FRAC rshift -rot3 \ mean sum2 inv_len precise_mean
      \ var = (((unsigned long long)sum2 * inv_len) >> FRAC) - (precise_mean * precise_mean >> (FRAC*2));
      dup um* nip FRAC 2 * 32 - rshift -rot \ mean precise_mean^2 sum2 inv_len
      um* 32 FRAC - lshift swap FRAC rshift or \ mean precise_mean^2 sum*inv_len
      swap - isqrt \ mean std
    ;
I've done all these things (except designing the hardware) and I agree that it can be very painful. I did some of them in 02008, for example: https://github.com/kragen/stoneknifeforth

The thing is, though, you can also not do all those things. You can use variables, and they don't even have to be allocated on a stack (unless you're writing a recursive function, which you usually aren't), and all the NIP TUCK ROT goes away, and with it all the Memory Championship tricks. You can test each definition interactively as you write it, and then the fact that the language is absurdly error-prone hardly matters. You can use metaprogramming so that your code is as DRY as a nun's pochola. You can use the interactivity of Forth to quickly validate your hypotheses about not just your code but also the hardware in a way you can't do with C. You can do it with GDB, but Forth is a lot faster than GDBscript, but that's not saying much because even Bash is a lot faster than GDBscript.

But Yossi was just using Forth as a programming language, like a C without local variables or type checking, not an embedded operating system. And, as I said, that's really not Forth's strength. Bash and Tcl aren't good programming languages, either. If you try to use Tcl as a substitute for C you will also be very sad. But the way they're used, that isn't that important.

I explained a more limited version of this 12 years ago: https://yosefk.com/blog/my-history-with-forth-stack-machines...

So, I don't think Forth is only useful when you have the freedom to change the problem, though programs in any language do become an awful lot easier when you have that freedom.

This item has no comments currently.