I'm amazed that it worked so well, it did confuse me that each repl didn't know the previously defined functions, is that just me?
Forth is almost the postfix inverse of lisp. Instead of arity errors, you have stack over and underflow. And it only has one list, instead of lists of lists.
Oh, and it's not garbage collected
Oh, it it's not homoiconic
{edit]I guess it's really not the same thing at all
Amazing how a day's exposure to Racket shifted my opinion
Is it as homoiconic as it needs to be? It's been a while since I've played with it in any real way, but, as I recall, Forth represents both data and code in exactly the same way: Blobs of data with no associated type information, that you're allowed to fiddle in any way you want, with no guard rails.
So it seems like there's no reason you couldn't write some words for manipulating code every bit as easily as you could write some words for manipulating any other data.
Lisp gives you a lot more out of the box, of course. But Lisp gives you a lot more of everything out of the box.
It depends on the implementation. With Indirect Threaded Code (ITC), "functions" are represented more or less as a list of other functions or primitives to call. But there are also classic bytecode-based Forth implementations, subroutine threaded code implementation (which is a simple form of native code generation), etc.
In my experience, Forth's "immediate" words, which let you execute code at compile time, combined with the availability of some (or most) of the compiler's part, let you do quite a lot of things.
In other words, you don't manipulate code, you directly generate code. For instance, if your implementation does not have 1+ (silly example), you can make a word "1+" that compiles "1 +" inline (or increment the top of stack if you interpret stuff from the REPL).
To answer your question, I use a dialect of Forth that has, I think, less capabilities than standard Forth in this area and rarely felt the need to implement them. At the risk of showing I am a blub programmer, I think homoiconicity is overrated - for the user (for language implementers maybe it's another story).
Lisp can take a chunk of lisp code and operate on it directly... forth can't do the same.
The big difference with forth is the inability to do things other than variables (fixed allocations) and use the stack. The handling of lists and garbage collected larger things on the heap are a huge advantage for the Lisper.
Forth doesn't need an abstraction for operating on threaded code; forth programmers routinely write their own words for control structures with an awareness of the internal structure of dictionary entries. You're operating on code-as-data, it's just an entirely different mechanism for doing so.
It's entirely possible to work with dynamically allocated memory in a Forth that runs on top of some other operating system, like GForth. When you're on metal, you can build whatever kind of allocator you want. The primitives "create"/"allot" are just that- primitives.
The comparison to Lisp always seems to pop up for some reason, but at the end of the day Forth draws very little, if any, inspiration from Lisp, and has very different functionality and evolutionary history. They are both "small" languages in some sense, but it is rare to see anyone claim that Brainfuck is a Lisp, or that they are somehow twins separated at birth if you turn your head to the right angle and squint.
It is better to simply learn about Forth instead of attempting to hammer it into the mold of another language one has heard of before.
> It is better to simply learn about Forth instead of attempting to hammer it into the mold of another language one has heard of before.
I knew Forth, I'm learning Racket (Lisp)... and I'd previously watched Uncle Bob Martin's talks about the quest for the ultimate programming language (Which at the time, he thought was Clojure)... it was then that I realized there is a continuum from Prefix (Lisp, etc) through infix (C, Pascal, Fortran, etc) to Postfix (Forth, Postscript, Cannon Cat, etc)
Stoical is a Forth that handles lists, dictionaries, etc... it was implemented on the DEC PDP-11, and formed the basis of the RED editor. It was then ported to Linux by the author who later wrote DAW.
I tried to revive it, but I don't really know C that well, and it made a LOT of assumptions about word size that I don't know how to get around in a 64 bit environment.
I strongly suspect you could write Lisp in Stoical and vise-versa.
Not sure if it counts as "industry" but FORTH-based Open Firmware is still used as a bootloader for some PowerPC machines. You can try this out under qemu:
$ qemu-system-ppc64
VNC server running on ::1:5900
$ vncviewer :0
Ready!
0 > 1 2 3 * + .
7 ok
0 > WORDS
(gigantic list of built-in words ...)
Even more than working in functional languages like SML, Forth (and RPL, my first stack language) taught me how to factor out code and remove/minimize duplication. It's just so obvious when using it where the duplication is, the hard part is coming up with decent names. But if a sequence of words can be given a good name, give it that name and define it.
You can install it on MCUs and use it to debug code pretty easily and makes it really nice to use reflection[1].
This use is not necessarily limited to enthusiasts, since nowadays even Arduino ends up in commercial products.
While the language itself it's considered difficult to read by some, it's a great way to access MCUs features in a stack-based way and at a level higher than assembly.
I've written a couple of FORTH-like implementations - one way back when on a Z80 system, when I was learning Z80 assembler, running CP/M, and one on an IBM PC (the original kind, with clicky keyboard) when I was learning 8086 assembler and a bit of C++, as part of an adventure-writing system. Unfortunately, the code for both has got lost (no git back then), but I can strongly recommend writing a FORTH as a way of learning a new (non-FORTH) language.
I use the standard keyboard. Don’t know what I can compare the look of it with. I’ve never seen or used an Android device. Maybe I can find a keyboard app with an Enter key.
Forth is almost the postfix inverse of lisp. Instead of arity errors, you have stack over and underflow. And it only has one list, instead of lists of lists.
Oh, and it's not garbage collected
Oh, it it's not homoiconic
{edit]I guess it's really not the same thing at all
Amazing how a day's exposure to Racket shifted my opinion