Thinking Forth: A Language and Philosophy for Solving Problems (2004) [pdf]
forth.com
forth.com
- JonesForth: https://github.com/nornagon/jonesforth/blob/master/jonesfort...
This is legit a text that goes the an x86 Forth implementation. Actually, it's just an implementation with really extensive comments. That said, including whitespace and comments, it's just 2000 lines and the pedagogy is excellent. Highly recommended for anyone who would rather see behind the curtain before picking up a larger text.
- SmithForth: https://dacvs.neocities.org/SF/
So, Smith decided to hand-write a Forth directly in x86-64 opcodes (well, the corresponding ascii hex bytes). It's incredibly slim and enlightening how you can bootstrap a language in just a couple hundred bytes or so.
This project actually inspired me to really learn the x86-64 architecture, so I ended up hand-decompiling the SmithForth binary instead of going through his commented implementation. Hand-decompilation is an absolutely fascinating exercise. You learn all about ELF structure, opcode encodings, and actually start to see the gaps where microarchitectural details shine through. Highly recommended for any hacker that really wants to grok low level details.
- Mecrisp: https://mecrisp.sourceforge.net/
An amazingly fast Forth implementation for MSP430, ARM, RISC-V, MIPS, and some FPGAs. This gave me one really nice understanding of Forth as
A REPL into your hardware!
- ##forth on libera.chatReally active and helpful members there. Definitely worth dropping by.
http://www.exemark.com/FORTH/eForthOverviewv5.pdf
https://www.forth.org/OffeteStore/1013_eForthAndZen.pdf
Another outstanding resources are the post from Bradford J. Rodriguez. Can't write a Forth implementation without going through the wisdom that's condensed in those links (see the first section):
This is what got me interested in Forth using ARM STM32 devices a couple years ago.
Specifically, I put Mecrisp-Stellaris Forth on an STM32F401. It was fun! You can experiment and quickly learn (fail fast) trying different features -- could try features of the chip as I read the datasheet.
I was able to translate those learnings to a C implementation as well.
I've enjoyed reading about FORTH and LISP over the years and I think LISP advocates have a similar philosophy. What Leo Brodie states so nicely is very hard for me to actually do. I think that's what separates the people who "get" computing from those (like me) who glue bits of various libraries together to get past the problem of the moment.
As an HP calculator lover (I wore the ENTER > = t-shirt 40 years ago) I understand the stack and RPN but have no idea how I'd write a trig or stat function if it weren't already built in!
Want to make a hacker laugh? Say "Forth is the dual of Lisp" to someone familiar with both languages. It seems they reach the same goal of a totally programmable programming language through completely opposite approaches.
Aside from the functional vs concatenative paradigms, they share a lot of development philosophy, and give a lot of the same superpowers to the developers.
Years ago I made it partway through this early LISP manual co-authored by a young John McCarthy before his move to Stanford: http://www.softwarepreservation.org/projects/LISP/book/LISP%...
I remember thinking:
1) They did not mess around in the 1960s. No "Hello World," no promises, no sales pitch. Just an in-yer-face "Here's how we do things downtown"
2) They defined a language in terms of itself. I still don't get all that implies but, damn, they can do that?
And you're right, there's absolute magic in old computing papers. They were pioneers. I wish we could see more of this pioneering spirit combined with todays silicon and ease of international communication.
Reminds me of the plethora of compilers written in the languages they're meant to compile. (Roslyn, Java compiler, F# compiler, etc.)
The spec for a language is harder to define than the compiler for it. The spec for Lisp is written in Lisp. And it's about half a page of Lisp code. And it's executable, which is not usually true with specs.
This is why reading the Lisp spec feels like reading "the Maxwell's equations of software" (to quote Alan Kay). It's a whole other fundamental model of computation, every bit as fundamental as a Turing machine, but much more practical. Nobody builds serious computing engines out of pure Turing machines, but people do it all the time with McCarthy machines.
They're both the same basic idea, just that Forth is a much more radical low-level implementation of that idea (e.g. it was just perfect for minimal 8-bit home computers).
Forth is execution that happens to have some syntax.
If you want a dual of lisp you need to look at Joy or Factor.
From talking to several people who've implemented things like this, I think they would've said the same thing before.
Nobody walks around knowing how to implement these kinds of things. If you need it, you just start trying, learning, reading, etc, until eventually you do it.
I worked at FORTH, Inc. one summer in the 80s before starting college. They sold a Forth system which they were converting to a new language standard, which (among other things) had changed the canonical booleans from 1-for-true to -1. One day I noticed the trig functions were giving wrong answers.
So I bring up the code with my boss, and it's pretty hard for us to figure out -- compact, no explanation, tables of random-looking numbers. Someone stops by (Dean Sanderson? iirc), we tell him what's up, he looks at the screen, and almost right away he's like "Oh, this is easy! All you need to do is swap the lines in the tables."
I tried gForth as well but during the installation, it invoked HomeBrew which gave a series of hostile messages that my system is obsolete and to not bother asking for any help or support. See [2] and the output provided by the poster - it is what I saw in my case.
[1] https://www.forth.com/download/
[2] https://superuser.com/questions/1767114/is-it-that-bad-to-us...
Well, that's not really about programmings skills though. That's math.
You could write a decent approximate SIN using the taylor series formula [1]. It's pretty easy, you don't even need to know math, can just look the formula up and translate it to an algorithm. Real world language SIN methods use more efficient and accurate methods, but it's still about knowing the math or looking up common such algorithms.
Or you could just invoke the libc (standard C library) SIN from Forth or whatever language you're using. That's what Python and other languages do.
The quote is more about the approach of writing an application by writing a DSL for the application, than about starting from zero and re-doing all the low level libraries like trig yourself.
I had no idea FORTH could invoke libraries from C. I got the impression it would be used on systems where space is at a premium precluding the installation of other higher-level languages.
https://www.complang.tuwien.ac.at/forth/gforth/Docs-html/Cal...
There are even bindings to C/C++ GUI libraries and so on. Running at constrained systems is just a common deployment scenario, but nothing in Forth necessitates it. You can even run it under Windows.
I would like to add though, that "language" does not have to mean macros and DSL. It can also simply mean what kind of things one considers primitives for the problem to solve. Those primitives can be built in already, they can be user defined functions (or words) or macros or whatever else makes an identifier or thing one can reference later when solving the actual problem.
If you want to do the parsed exterior DSL thing today, the magic wand that probably does it the best is Raku and its souped-up grammar system. I actually am exploring that now and I think it has a good toolkit for prototyping anything resembling a textual interface.
on: What are the enduring innovations of Lisp? (2022):
https://news.ycombinator.com/item?id=36159999
>PostScript is as truly homoiconic and polymorphic and interactive as Lisp.
on: Masterminds of Programming: Chuck Moore (2009):
https://news.ycombinator.com/item?id=21964186
on: Sun's NeWS was a mistake, as are all toolkit-in-server windowing systems (2013) (utoronto.ca):
https://news.ycombinator.com/item?id=22456471
FORTH ?KNOW IF
HONK!
ELSE
FORTH LEARN!
THEN
https://news.ycombinator.com/item?id=29261771on: Forth vs Lisp:
https://news.ycombinator.com/item?id=29261810
NeWS PostScript stuff:
https://news.ycombinator.com/item?id=22456831
Lisp in Forth:
Can't resist reposting this:
https://news.ycombinator.com/item?id=39109122
3rd comment down the subthread.
Forth is also a pretty good development target, if you need a "fully featured" stack VM with a repl. There's never been a requirement that using Forth means "writing the entire system in a Forth that you bootstrapped yourself". Sometimes you want to have a little build step on top, and sometimes you want to target a system that has more than the minimalistic or standards-driven stuff, or you want to have a small interpreter over library code that has implemented the fast algorithms already. Forth systems tend to be personalized, quirky, and under-documented, but most are also easy to strip down and examine closely.
When I recommend this book to people I like to say: "it was talking about TDD, modularity, iterative development, and all your _cool things_ back in the 80s ...".
Good programming ideas are nothing new.
It starts by explaining what is a stack, and by the end you could implement your own Forth.
And it shows how those two tasks can be one and the same.
(is this what you meant by "example pitch"? I'm not familiar with that term)
Forth gives an even more direct experience than the microcomputer BASICs did: you wrote a word, it was a number so it went on a stack, then you wrote a different word, and it popped the number from the stack. You allocated memory with ALLOT. Now when you run HERE(the address of the bump allocator), you see that it moved up by the amount that you passed to ALLOT. You can use SEE to explore word definitions and get a sense of how much of the language is implemented in itself. You can explore the double number arithmetic to learn fixed point maths.
It just poses a certain clarity and lack of restriction that is only limited by how much the programmer can reason through their abstractions. Thinking Forth helps with that, in that it shows that you can often solve things in a simpler way than you thought.
Thinking Forth (1984) - https://news.ycombinator.com/item?id=33679360 - Nov 2022 (49 comments)
Starting FORTH (1981) - https://news.ycombinator.com/item?id=33674486 - Nov 2022 (24 comments)
Starting Forth: An Introduction to the Forth Programming Language - https://news.ycombinator.com/item?id=26677630 - April 2021 (19 comments)
Recommended Reading: ``Starting Forth'' and ``Thinking Forth'' by Leo Brodie - https://news.ycombinator.com/item?id=20193620 - June 2019 (1 comment)
Thinking Forth – A Language and Philosophy for Solving Problems (1984) [pdf] - https://news.ycombinator.com/item?id=18885493 - Jan 2019 (41 comments)
Starting Forth - https://news.ycombinator.com/item?id=15164448 - Sept 2017 (5 comments)
Starting Forth - https://news.ycombinator.com/item?id=9855977 - July 2015 (68 comments)
Thinking Forth (1984) - https://news.ycombinator.com/item?id=9842557 - July 2015 (31 comments)
Starting Forth – the classic Forth language tutorial - https://news.ycombinator.com/item?id=5909968 - June 2013 (32 comments)
Thinking Forth - https://news.ycombinator.com/item?id=3389286 - Dec 2011 (21 comments)
Starting Forth - After yesterday's Prolog post, another awesome language - https://news.ycombinator.com/item?id=1980123 - Dec 2010 (27 comments)
Starting Forth - https://news.ycombinator.com/item?id=448303 - Jan 2009 (7 comments)
Back when those came out I used a dozen of them on a serial network to run a custom robot. As part of that project I designed a floppy disk controller, paged memory expansion boards, motor control and encoder interface boards, control panel interface and more.
In case the context isn’t clear to some, no Internet, no Arduino…you couldn’t buy a bunch of little boards to solve problems. The entire project consisted of a couple dozen wire-wrapped STD-44 boards. Like these:
https://www.farnell.com/datasheets/1801376.pdf
I also wrote my own file manager and code editor.
All in Forth.
Burgess had been using FORTH on his Ohio Scientific, so I suppose the transition to another 6502-core was probably pretty easy!
This is what I've wired up so far:
https://i.imgur.com/a0fvjqa.jpg
Here are the front pages of three data sheets I have:
https://i.imgur.com/fPgRzc7.jpg
https://i.imgur.com/EeFNT8j.jpg
https://i.imgur.com/kmRsyXq.jpg
In the documentation set I have a full printed listing for some version of the code editor I wrote as well as a pile of utilities and drivers. This is dating back almost exactly 40 years.
Also have the schematics for various interface boards, including a floppy disk interface board and, I believe, the driver I wrote to run screen-based code storage and retrieval from it. This was a very long time ago. I can't remember how closely these schematics and code matched working hardware.
If any of this could help you I might be able to scan and post somewhere. It will take some work because I have to use a flat-bed scanner. It's amazing how well paper and vellum survive four decades inside a binder.
We did a R6501Q based SBC a number of years ago, and eventually got RSC FORTH kernel and development ROMs running on it. We'd found a copy of the ROM object code in Burgess's archives and got it going from that. I want to eventually add a floppy controller to it, a friend had been working on replacing some of the floppy-based screen storage with CompactFlash backed storage, but got busy on other things.
What was the intended purpose for your R65F11 hacking?
GForth is pretty good, the docs and tutorial are a great way to get started and the implementation is still actively developed.
- Why is shell script more succinct than JavaScript at some things
- How would I do something like unix pipes in JS
- The JS pipe proposal F# syntax
- Tacit programming
- Concatenative languages
I find for a lot of these esoteric programming languages and paradigms, most people just don't have the right motivation to explore them. So we are just stuck with OO everywhere. But once you pull on the right threads and start questioning the status-quo, you really start to gain a deeper understanding and realize why things are so complex.
(That said, I don't like FORTH much at all. The amount of stack-thinking is just agony).
https://santhoshkris.medium.com/threading-macros-in-clojure-...
I'll sometimes abuse Python's compose to do similar things I won't send out for code review. Maybe I really should just try to live in Coconut instead of silly stuff like:
import chess
import chess.svg
from IPython.display import SVG, display
from functools import reduce
def rcompose(*fs):
return reduce(lambda f, g: lambda *xs, **ys: g(f(*xs, **ys)), fs)
inline_board = rcompose(
chess.Board,
chess.svg.board,
SVG,
display)
Factor's quotations dealing with stack management weirdness is super nice, too.https://concatenative.org/wiki/view/Concatenative%20language...
It still has a bit more stack juggling than I like, though. That could just be a "me" problem. Props to that whole community for their effort.
It has the most charming illustrations I've ever seen in a text book.
Both excellent, well written books
Link to my post on this thread about a Forth-based robot controller I designed back in 1984 using a dozen R65F11 Rockwell CPU's that came out of the box running Forth:
https://news.ycombinator.com/item?id=39298559
Schematics and other notes in one of my replies.
However I quickly realised why it was callled a WOL (write-only language - was a pun on RAM / ROM acronyms), as it was hard to understand my own code sometimes only days later.
Never looked back. Actually i did look back, at the beauty of the language, but never been tempted to actually use it.
DonHopkins on Jan 13, 2023 | parent | context | favorite | on: What the hell is Forth? (2019)
This is a great article! I love his description of Forth as "a weird backwards lisp with no parentheses".
Reading the source code of "WAForth" (Forth for WebAssembly) really helped me learn about how WebAssembly works deep down, from the ground up.
It demonstrates the first step of what the article says about bootstrapping a Forth system, and it has some beautiful hand written WebAssembly code implementing the primitives and even the compiler and JavaScript interop plumbing. We discussed the possibility of developing a metacompiler in the reddit discussion.
I posted this stuff about WAForth and a link to a reddit discussion with its author in the hn discussion of "Ten influential programming languages (2020)":
https://news.ycombinator.com/item?id=34056735
Yes, I agree FORTH should be probably be on the list, at least if the list was a few languages longer, for as influential as it's been.
WAForth for WebAssembly is beautiful and modern!
https://github.com/remko/waforth
It's a lovingly crafted and hand written in well commented WebAssembly code, using Racket as a WebAssembly macro pre-processor.
I learned so much about WebAssembly by reading this and the supporting JavaScript plumbing.
The amazing thing is that the FORTH compiler dynamically compiles FORTH words into WebAssembly byte codes, and creates lots of tiny little WebAssembly modules dynamically that can call each other, by calling back to JavaScript to dynamically create and link modules, which it links together in the same memory and symbol address space on the fly! A real eye opener to me that it was possible to do that kind of stuff with dynamically generated WebAssembly code! It has many exciting and useful applications in other languages than FORTH, too.
Lots more discussion and links in the reddit article.
But here's the beef, jump right in:
https://github.com/remko/waforth/blob/master/src/waforth.wat
Reddit /r/Forth discussion of WAForth:
https://www.reddit.com/r/Forth/comments/zmb4eb/waforth_wasmb...
remko:
Author here
If you can't be bothered to install VS Code, you can have a look at a standalone version of the example notebook (in a 26kB self-contained page).
And if you're planning to go to FOSDEM 2023, come say hi: I'll be giving a talk there on WebAssembly and Forth in the Declarative and Minimalistic Computing devroom.
DonHopkins:
I really love your tour-de-force design and implementation of WAForth, and I have learned a lot about WebAssembly by reading it. Never before have I seen such beautiful meticulously hand written and commented WebAssembly code.
Especially the compiler and runtime plumbing you've implemented that dynamically assembles bytecode and creates WebAssembly modules for every FORTH word definition, by calling back to JavaScript code that pulls the binary bytecode of compiled FORTH words out of memory and creates a new module with it pointing to the same function table and memory.
WebAssembly is a well designed open standard that's taking over the world in a good way, and it also runs efficiently not just in most browsers and mobile smartphones and pads, but also on the desktop, servers, cloud edge nodes, and embedded devices. And those are perfect target environments for FORTH!
What you've done with FORTH and WebAssembly is original, brilliant, audacious, and eye-opening!
I'd read the WebAssembly spec before, and used and studied the Unity3D WebAssembly runtime and compiler to integrate Unity3D with JavaScript, and I also studied the AssemblyScript subset of TypeScript targeting WebAssembly and its runtime, and also Aaron Turner's awesome wasmboy WebAssembly GameBoy emulator .
I first saw your project a few years ago and linked to it in this Hacker News discussion about Thoughts on Forth Programming because I thought it was cool, but it's come a long way in three years, and I'm glad I finally took the time to read some of your code, which was well worth the investment of time.
Until reading your code, I didn't grasp that it was possible to integrate WebAssembly with JavaScript like that, and use it to dynamically generate code the way you have!
Also, the way you used Racket as a macro assembler for WebAssembly was a practical and beautiful solution to the difficult problem of writing maintainable WebAssembly code by hand.
Even for people not planning on using FORTH, WAForth is an enlightening and useful example for learning about WebAssembly and its runtime, and a solid proof of concept that it's possible to dynamically generate and run WebAssembly code on the fly, and integrate a whole bunch of tiny little WebAssembly modules together.
Playing with and reading through your well commented code has really helped me understand WebAssembly and TypeScript and the surface between them at a much deeper level. Thank you for implementing and sharing it, and continuing to improve it too!
remco:
Wow, thanks a lot, I really appreciate that! It makes me very happy that I was able to get someone to learn something about WebAssembly by reading the source code, which is exactly what I was going for.
[More links and discussion of WAForth, WebAssembly, and Forth Metacompilers:]
https://www.reddit.com/r/Forth/comments/zmb4eb/waforth_wasmb...
Here's the author's blog post about WAForth:
A Dynamic Forth Compiler for WebAssembly