Stepping away from Forth in particular, one of the benefits of a stack-based / concatenative language is that it's easy to implement on constrained hardware. uxn [1] is a great example of that.
And shameless self-promotion, if you're interested in how these kinds of languages compare with more traditional named-based languages, with more theoretical constructs like the lambda calculus and combinatory logic, and with gadgets like a PyBadge — well you're in luck! I gave a talk about exactly that at the final Strange Loop [2].
This is long winded, but maybe you have some thoughts here.
I've been building a DOM-builder API recently in Rust. The existing options (there are many) tend to use textual templating, which can't reason well about anything, or basic macros, which never support indentation. I wanted something that was just code, where I'd be in full control on the indentation (or lack thereof) programmatically. The closest equivalent is Python's Dominate [1], though its indentation mechanisms are buggy.
So I built a system using the traditional tree where Nodes own other Nodes at random addresses, and I built a renderer that renders those nodes and concatenates their strings recursively. It ended up working but it was hacky and very slow for the large inputs. In release mode, it was taking almost a minute to render 70 files, and I want about two orders of magnitude lower.
I ran it through profilers and optimized it a bit, but wanted to see if I could simplify the architecture and reduce the amount of work the computer could do. I read about flattening ASTs [2] and how through optimizing that format, you can end up with a sort of bytecode [3]. I also looked into Data-Oriented Design, watching Mike Acton's famous talk [4], Andrew Kelley's talk about DoD in Zig [5], and reading through the DoD book by Richard Fabian [6].
I ended up with something that works quite well for traversing and rendering, which is a stack that can be traversed and rendered in O(n), but I lost my nice Dominate-like API. As in, I can build these beautiful, flat trees, but to embed those trees in my code, I need to either materialize a tree in the traditional style first and then push it onto these stacks, or do some sort of macro magic to make these stack pushes.
I wonder if this is a common issue with stack-based programming. It is, in my case, quite simple for the computer, but hard to fit into an API without building up the stack manually!
And shameless self-promotion, if you're interested in how these kinds of languages compare with more traditional named-based languages, with more theoretical constructs like the lambda calculus and combinatory logic, and with gadgets like a PyBadge — well you're in luck! I gave a talk about exactly that at the final Strange Loop [2].
[1] https://100r.co/site/uxn.html
[2] https://dcreager.net/talks/concatenative-languages/