Forth has been something I've wanted to learn for years now. It seems weird to me that for most stuff in old computers, you have the option of "assembly" if you want your program to be fast, and "BASIC" if you want your program to be slow, but Forth lingers along as the "medium speed" language, despite at least looking pretty high-level.
The reason I used FORTH to code ChipWits in 84 was twofold. First, it allowed me to develop natively on the 128k Mac rather than buying an outrageously expensive Lisa. Second, I knew I was going to port it to other micros and FORTH was usually one of the first languages implemented on new computers. I eventually ported it to Apple II and C64 and about 70% of the Mac code was easily portable.
It may look more high-level than something like C, but it is actually no more high level than a macro assembler with registers eliminated. As there's no syntax tree, essentially every word that is parsed from the input stream is replaced with a subroutine call. So the resulting FORTH code is nothing but a series of subroutine calls.
In my experience quite often writing in assembler is easier than FORTH unless you have a strategy and self discipline, which when acquired makes one a whole lot more productive than using assembler, and arguably more so than a high level language. There're no pointer arithmetics, no rudimentary type checking, not even an array type (you have cells and addresses). There is nothing that throws an error except things like stack over/under-flow checks, and if you are lucky your code will crash. If not debugging can be tricky. Stack imbalances won't be reported/checked for you, there is no bounds checking for anything (not even structs). But there are conventions/strategies to prevent these kinds of bugs from happening that one needs to either discover for themselves, or find out in books (the book Thinking Forth helps, but is not enough I would say).
Working with the stack can be more difficult than with registers, although the latter can be easily simulated with variables, which is often frowned upon. But words like CREATE ... DOES> enables meta-programming that helps with generating code with code, and makes it quite powerful, but can make your code complicated to reason about (see the concepts of compilation vs. execution vs. interpretation semantics described in ANS Forth).
In the end the appeal of FORTH for me is in its "simplicity" (but nowhere any ease of use as it requires mastery of laying out code in memory as you would do in an assembler without any help from the language itself), its overall philosophy (see Chuck Moore's A Problem Oriented Language) on focusing on the nature of the problem rather than thinking in terms of the tools/language given to you (build a "language" for the problem), and providing solutions with as minimal "cruft" as possible.
Anything that you say is missing can be added. I'm no expert but when I had some confusion about the stack I would create a word that did something in a balanced way, test it quickly, and use that word instead to build on. Forth makes it easy to climb the levels abstraction quickly.
The method that it uses to interpret/compile a word varies by implementation. Subroutine call is just one of them.
Very fast (faster than naive assembler) but not at all high-level; having to look after the stack is a bit of a pain. Writing your own FORTH is fun - it doesn't need to be in assembler - I once wrote a FORTH-like scripting language in C++.
but it's also very extendable. It's ability to slap on new control structures and DSL's is on par with Lisp. I'd say it's very low level and much higher level than the most languages simultaneously.
Yeah, that's what I was kind of getting at. It looks like it starts low level, but it seems like it allows effectively an infinite amount of abstraction.
One of the great things about it was, it came with an assembler vocabulary to code your inner loops or other lowest-level stuff in. I gather BBC Basic had something like that, but I never saw and and I did get to use Forth in this way back in the day. Most of those systems made it harder to flexibly mix the higher and lower-level coding.
I think writing a toy Forth interpreter is a good way to learn about the language. It's easy and I had a lot of fun with it. But it is so ridiculously easy, at least up to a certain point, some may find it too elementary, or too tempting to go beyond a toy implementation.
Forth is very good for writing small software in tight memory constraints. Unfortunately it is pretty hard to read; for bigger software projects there are many better languages.
Relatedly, there's http://tumbleforth.hardcoded.net/, which I think looks lovely. Has anyone gone through that and would like to share their experience?
I got about halfway through it during a slow work week. It was a throwback to my hardware classes from college. It got me thinking differently about computing.
I am young and stupid, but from a rear-view perspective it looks like maybe certain abstractions were chosen in the old days when there were hardware limitations, and that our current "evolutionary branch" of programming languages has a lot of abstractions that have not aged well, leading to a lot of layers of load-bearing cruft --much like any engineering project.
Collapse OS might not be practical today, but it has a "liberating" appeal. Freeing yourself from all these layers of abstraction sounds really enticing. A way to enjoy computing as it existed in the 1960s, but without the terrible developer experience. (or so I imagine)
Currently my pie-in-the-sky project would be to work through these projects, get Dusk OS building on a virtual machine, then physical machine, then write a Scheme interpreter for Dusk OS in C --and go hog-wild from there.
I have a couple of rivers to cross before I get there. I implemented a Scheme interpreter in Python in a couple of hours, then improved the scanner/Tokenizer in a couple more hours. Now I'm reading through crafting interpreters to see how I would go about implementing a Scheme interpreter in C. After that's done and I implement an interpreter in C, I'll revisit this guide and try to jump headfirst into DuskOS.
Just following up on this - this comment was my initial excitement at seeing some real Forth-based thing. I've had time since then to follow up and read the wikipedia page for ChipWits now and the blog post: the original game looks very cool. The logo from the manual on WP is so great.
I'd been making a list recently of games (old and new) that have puzzles and programming type stuff in them. It's going on the list! I could very well get on to it next after I'm finished the ketman assembly "game" (although it's not really a game, I suppose).
We kept the gameplay of the original pretty much intact in the new game.
I don't want to spam Hacker News, but since you played the original, I'd love to get your reaction to the reboot: https://chipwits.com
Forth seems to be one of those write once languages like perl. Easy to start writing and building, but come back to the code in a year or so, no clue what it does.
That's awesome. I will! I was probably around 12-14? when I spent many hours with that game. After that it was DOS and Doom. But I think when I eventually drifted towards the path to being a software engineer I did grasp a lot of the basic concepts faster because I played games like this as a kid. The other path was being a musician of course.
Here's a post I wrote about why I used FORTH to code ChipWits in 84:
https://chipwits.com/2023/04/08/forth-programming-language-g...
Forth has been something I've wanted to learn for years now. It seems weird to me that for most stuff in old computers, you have the option of "assembly" if you want your program to be fast, and "BASIC" if you want your program to be slow, but Forth lingers along as the "medium speed" language, despite at least looking pretty high-level.
Forth was the standard language for hardware development and drivers (along wiht C) for a very long time (still is used all over). Stack based.
https://www.forth.com/starting-forth/
The reason I used FORTH to code ChipWits in 84 was twofold. First, it allowed me to develop natively on the 128k Mac rather than buying an outrageously expensive Lisa. Second, I knew I was going to port it to other micros and FORTH was usually one of the first languages implemented on new computers. I eventually ported it to Apple II and C64 and about 70% of the Mac code was easily portable.
Thanks for opening the source code to another generation
Yeah I knew that, that's why I've found it interesting.
It looks a lot more high-level than something like C, but is used in similar spaces, which makes me wonder why it never really became more popular.
It may look more high-level than something like C, but it is actually no more high level than a macro assembler with registers eliminated. As there's no syntax tree, essentially every word that is parsed from the input stream is replaced with a subroutine call. So the resulting FORTH code is nothing but a series of subroutine calls.
In my experience quite often writing in assembler is easier than FORTH unless you have a strategy and self discipline, which when acquired makes one a whole lot more productive than using assembler, and arguably more so than a high level language. There're no pointer arithmetics, no rudimentary type checking, not even an array type (you have cells and addresses). There is nothing that throws an error except things like stack over/under-flow checks, and if you are lucky your code will crash. If not debugging can be tricky. Stack imbalances won't be reported/checked for you, there is no bounds checking for anything (not even structs). But there are conventions/strategies to prevent these kinds of bugs from happening that one needs to either discover for themselves, or find out in books (the book Thinking Forth helps, but is not enough I would say).
Working with the stack can be more difficult than with registers, although the latter can be easily simulated with variables, which is often frowned upon. But words like CREATE ... DOES> enables meta-programming that helps with generating code with code, and makes it quite powerful, but can make your code complicated to reason about (see the concepts of compilation vs. execution vs. interpretation semantics described in ANS Forth).
In the end the appeal of FORTH for me is in its "simplicity" (but nowhere any ease of use as it requires mastery of laying out code in memory as you would do in an assembler without any help from the language itself), its overall philosophy (see Chuck Moore's A Problem Oriented Language) on focusing on the nature of the problem rather than thinking in terms of the tools/language given to you (build a "language" for the problem), and providing solutions with as minimal "cruft" as possible.
Anything that you say is missing can be added. I'm no expert but when I had some confusion about the stack I would create a word that did something in a balanced way, test it quickly, and use that word instead to build on. Forth makes it easy to climb the levels abstraction quickly.
The method that it uses to interpret/compile a word varies by implementation. Subroutine call is just one of them.
Very fast (faster than naive assembler) but not at all high-level; having to look after the stack is a bit of a pain. Writing your own FORTH is fun - it doesn't need to be in assembler - I once wrote a FORTH-like scripting language in C++.
but it's also very extendable. It's ability to slap on new control structures and DSL's is on par with Lisp. I'd say it's very low level and much higher level than the most languages simultaneously.
yes, that's what i did on the C++ implementation i mentioned. it was for writing the action parts (not the parser etc.) for a text adventure system.
Yeah, that's what I was kind of getting at. It looks like it starts low level, but it seems like it allows effectively an infinite amount of abstraction.
One of the great things about it was, it came with an assembler vocabulary to code your inner loops or other lowest-level stuff in. I gather BBC Basic had something like that, but I never saw and and I did get to use Forth in this way back in the day. Most of those systems made it harder to flexibly mix the higher and lower-level coding.
I think writing a toy Forth interpreter is a good way to learn about the language. It's easy and I had a lot of fun with it. But it is so ridiculously easy, at least up to a certain point, some may find it too elementary, or too tempting to go beyond a toy implementation.
Even just reading through an existing implementation can be very enlightening. E.g. JonesForth (where like 90% of the assembly source is comments explaining everything in detail): https://github.com/nornagon/jonesforth/blob/master/jonesfort...
Forth is very good for writing small software in tight memory constraints. Unfortunately it is pretty hard to read; for bigger software projects there are many better languages.
I once heard Forth called a "write-only language."
I so desperately wanted this game as a kid.
Man I'm getting old.
Looks very cool!
Relatedly, there's http://tumbleforth.hardcoded.net/, which I think looks lovely. Has anyone gone through that and would like to share their experience?
I got about halfway through it during a slow work week. It was a throwback to my hardware classes from college. It got me thinking differently about computing.
I am young and stupid, but from a rear-view perspective it looks like maybe certain abstractions were chosen in the old days when there were hardware limitations, and that our current "evolutionary branch" of programming languages has a lot of abstractions that have not aged well, leading to a lot of layers of load-bearing cruft --much like any engineering project.
Collapse OS might not be practical today, but it has a "liberating" appeal. Freeing yourself from all these layers of abstraction sounds really enticing. A way to enjoy computing as it existed in the 1960s, but without the terrible developer experience. (or so I imagine)
Currently my pie-in-the-sky project would be to work through these projects, get Dusk OS building on a virtual machine, then physical machine, then write a Scheme interpreter for Dusk OS in C --and go hog-wild from there.
I have a couple of rivers to cross before I get there. I implemented a Scheme interpreter in Python in a couple of hours, then improved the scanner/Tokenizer in a couple more hours. Now I'm reading through crafting interpreters to see how I would go about implementing a Scheme interpreter in C. After that's done and I implement an interpreter in C, I'll revisit this guide and try to jump headfirst into DuskOS.
Ok, I'm tempted to go back to it, thanks for sharing your experience! I have had some ideas similar to what you describe. I wonder if you've seen https://wiki.xxiivv.com/site/uxntal.html. Some of the projects listed here might be of interest to you either https://malleable.systems/catalog/
Just following up on this - this comment was my initial excitement at seeing some real Forth-based thing. I've had time since then to follow up and read the wikipedia page for ChipWits now and the blog post: the original game looks very cool. The logo from the manual on WP is so great.
I'd been making a list recently of games (old and new) that have puzzles and programming type stuff in them. It's going on the list! I could very well get on to it next after I'm finished the ketman assembly "game" (although it's not really a game, I suppose).
I hope the new ChipWits does excellently!
I played it a lot on the Commodore 64 when I was a kid. Unique, curious and entertaining.
We kept the gameplay of the original pretty much intact in the new game. I don't want to spam Hacker News, but since you played the original, I'd love to get your reaction to the reboot: https://chipwits.com
Forth seems to be one of those write once languages like perl. Easy to start writing and building, but come back to the code in a year or so, no clue what it does.
But really fast and efficient.
Curious, what is the modern version of Chipwits is written in?
They mention that it's C# and that it's at least 10x the amount of code...
I loved this game! I actually had the Forth package for the C64 also but I never put 2+2 together that the game was made with it.
Glad you dig my old game. Play our demo on Steam!
https://store.steampowered.com/app/2330720/ChipWits/
That's awesome. I will! I was probably around 12-14? when I spent many hours with that game. After that it was DOS and Doom. But I think when I eventually drifted towards the path to being a software engineer I did grasp a lot of the basic concepts faster because I played games like this as a kid. The other path was being a musician of course.
Stacks in ChipWits were very much a result of coding the game in FORTH.
Unity in C#