> That's a bit off-topic but I would say [to get memory safety you should use] any interpreter for a dynamically typed language that use a GC. That is to say almost anything but Forth (at least in the non-AoT category)

Okay, but if you use, say, Lua instead of Forth, you're going from an interpreter that weighs 4 kilobytes to one that weighs 100 kilobytes. And instead of running 5 times slower than C (assuming a conventional threaded-code Forth), it runs 20 times slower (assuming not LuaJIT). And you've lost inline assembly. And you've lost compile-time metaprogramming (and if you want eval, which lets you get some of it back, the price goes up to 150 kilobytes). And you can no longer write real-time code because of the GC. And, even without real-time requirements, your programs randomly fail in limited-memory environments because they're allocating all the time, and sometimes they suffer atypical allocation fragmentation. And the memory requirements aren't just unpredictable, they're also large, because most of your memory is taken up by pointers, so even when your programs don't crash randomly in a low-memory environment they can't do as much as Forth.

There are other compact interpreted languages with other tradeoffs: BASIC, Smalltalk, XLISP, ZIL, Red, Elisp, and PostScript, for example. But they all have many or all of the above drawbacks.

So I don't think it's unreasonable to try to find a spot in the design space that's closer to Forth than it is to Lua and PostScript. GC and dynamic typing clearly aren't necessary for memory safety. The resulting language clearly wouldn't be the same thing as Forth, but that doesn't mean it has to have the kinds of orders-of-magnitude disadvantages listed above.

> If it is really important not to off-by-one, you can make your array a power of two in size, and then access it through "gate keeping" words that bitmask the index. Or perform a quick check on the passed index using the same technique.

This is going to the opposite extreme from "fail fast": unless the desired semantics is really an infinitely replicated buffer, like if you're using it as a ring buffer, this is deliberately producing incorrect results to mask the programming error of an out-of-bounds index. There are situations where that's a good idea (any possible way of handling such an error in an NPC script in a first-person shooter would be better than crashing the game, and ring-buffer FIFOs are a perfectly reasonable way to communicate with interrupt handlers and real-time threads) but there are also a lot of situations where failing fast is better.

> I have no idea of how many people are using Forth in production, as a hobby, as a personal tool or as a puzzle game.

My objection to your comment was basically that you seemed to be saying that anyone who's using Forth as something other than a puzzle game is doing it wrong.

Yes, doing things in a way that's more difficult than necessary is a worthwhile activity and makes you stronger. Football players get better at playing football by lifting weights. But they don't carry the weights with them onto the football field. That would make them worse at playing football.

> Specialization leads to simplification, generalization often leads to complications.

An important insight. You're right about the history of Forth, too.