It's a bit unfortunate that this article is one of the most circulated accounts of a "failure" of applying Forth to a real-world problem. The author learned a little about Forth and was fascinated. He then wrote his own implementation and struggled mightily with it. Ultimately he was disenchanted.
I think the heart of the problem is that the rudimentary ideas of forth- a stack, some stack-shuffling words, some arithmetic, control flow, and that's about it- are appealingly simple, but not enough of the language:
>"I figured I didn't need the more interesting metaprogramming stuff for my first prototype programs, and I could add it later if it turned out that I was wrong. It was wierd to throw away everything I originally liked the most, but I was all set to start writing real programs. Solving real problems in the real world. It was among the most painful programming experiences in my life."
Imagine reading the first chapter of SICP without prior exposure to Lisp, excitedly writing an interpreter for the parts of the language you'd seen so far, and then feeling your enthusiasm slowly slip away into dismay as you attempted to use that stunted fragment of a language to get work done.
Forth can be small, and simple, but the real gems of the language are a bit subtle. The many implications of CREATE>/DOES. Abuses of manipulating the rstack. Striking a balance between parsing words, named locals, global variables, vocabularies, and other tools to minimize twisty stack shuffling. Bending the rules at the right times.
I am fascinated by forth and stack machines. It reminds me of Donella Meadows' Leverage Points, when you change your paradigm from data in registers to that in stack, the architecture becomes simpler.
Can you please suggest any reference which explores forth in depth and goes into the subtleties. I am starting out on the Leo Brodie books.
These are "old" references, as a lot of Forth references seem to be but I enjoyed them during a Forth phase. The standard advice, and I agree with it, is write your own Forth, maybe more than one. If you're comfortable in any platform's assembly language I would recommend starting there, even if it's "old". This depends on your own history in computing but I found a C64 emulator convenient for this. Old PC emulators have load/save abilities to the host file system, and what I loved was a simple memory model, memory-mapped hardware features, and a simple ISA. i.e. a system you can hold in your head all at once, contrasted with modern handhelds or desktops.
Two books: (I really enjoyed the first one, multiple times)
"Threaded Interpretive Languages", by R. G. Loeliger.
"Stack Computers: The New Wave", by Philip Koopman.
Two short papers: (maybe not profound, but they're short and available online)
"Object Oriented Forth" by Dick Pountain is a succinct and practical exploration of applying Forth's metaprogramming capabilities to extend the language with various features. The best aspect of the book is that it works through many alternatives rather than taking a direct path. It's more about data structures and abstraction than OOP.
I love Forth and and have implemented it (well, not compliant) twice (Z-80 and C) back in the day for fun.
Postscript should get a mention, as its a related surviving stack language (though higher level - but in the spirit of the article, for a very domain-specific purpose), even if printer drivers do all the coding.
Though they changed most of the word names to protect the innocent: http://hyperpolyglot.org/stack
(And lest we forget display Postscript a la Sun NeWS - boy that was fun stuff! - still the coolest way to write your own desktop widgets)
Speaking of NeWS fun - I remember playing tricks on a colleague by logging into their display server using psh and manually tweaking the transformation matrix for a terminal window so that it very gradually rotated as he was using it. Of course, as it was NeWS (actually HyperNeWS) everything just worked until the rotation became really obvious.
I didn't really appreciate Forth until I found Jonesforth [0], a very well-documented Forth implementation in a single x86 assembly file. You can read it from top to bottom and gain a pretty good understanding of how a Forth can be implemented.
I agree! I found jonesforth's literate source so exciting that I went off and implemented FORTH 83 in Julia. Sadly though, Jonesforth doesn't implement create/does...
Forth programmer from the late '70s here. It was great for self-contained "smart" instruments. (I worked on a magnetometer at UCLA.) But, unfortunately, I never had occasion to work with it again.
But, it was definitely one of the most "out there" languages I ever used...
The further down I read this the more tremendous it gets. The author has an insight which matches my observations:
> What does this say about Forth? Not much except that it isn't for me. Take Prolog. I know few things more insulting than having to code in Prolog. Whereas Armstrong developed Erlang in Prolog and liked it much better than reimplementing Erlang in C for speed. I can't imagine how this could be, but this is how it was. People are different.
People are different. Programming is building a model in your head then transferring that to a set of machine actions. (See "Programming as theory building", https://news.ycombinator.com/item?id=10833278 ) It appears that different people's head-models are radically different, and that what they find easy is different.
This renders discussions about "intuitive" moot, because it's no longer universal. To whom is it intuitive? You can define a target audience and survey them to find it out, or you can guess that what's intuitive to you is intuitive to others - but you can't guarantee it will be intuitive to everyone.
Further down:
> This is Forth. Seriously. Forth is not the language. Forth the language captures nothing, it's a moving target. Chuck Moore constantly tweaks the language and largely dismisses the ANS standard as rooted in the past and bloated. Forth is the approach to engineering aiming to produce as small, simple and optimal system as possible, by shaving off as many requirements of every imaginable kind as you can.
This appears to be the key to the productivity claims: junking requirements along the way. That also matches the broader experience of software engineering: you can be very productive writing for yourself at one end, but on the other there are colossal state megaprojects that never work because the requirements are incoherent and immovable. Hence "agile": what agile really provides is an opportunity every week or two to chip away at the requirements until something deliverable is decided upon.
> MD5 presents a few problems for programming a Green Arrays device. For one thing it depends on modulo 32 bit addition and rotation. Green Arrays chips deal in 18 bit quantities. For another, MD5 is complicated enough that neither the code nor the set of constants required to implement the algorithm will fit into one or even two or three nodes of a Green Arrays computer.
> I'm the person who was dissecting colorforth, a dead frog. The comment from Jeff Fox is totally unfair. The only reason I did it was THAT COLORFORTH JUST DIDN'T RUN ON THE THREE MACHINES I HAD AVAILABLE. And he nor Chuck Moore had any consideration with people like me or would waste their time helping me get colorforth up and running. I never managed to run colorforth, until such time as others made an emulation environment to boot a floppy image under windows. (Did you know that colorforth is just a floppy image?)
Lack of adoption seems hardly surprising under these circumstances.
That’s a great point about the term “intuitive”. Our intuition is based on our own experience, so it is necessarily different for each of us. But we can at least unite around shared experience, our cultural heritage and language. User interface idioms (double tap to zoom), videogame tropes (there is a button you hold to run), or typical standard library calls (here is how to fmt a string) all correspond to communities that know them. The beauty of learning lisp, forth, ML, prolog, verilog is not only that you grow your intuition but also that they help you better reflect on the boundaries of your knowledge and its finite extent. So much disagreement online is simply because we come from non-overlapping communities that use the same words to describe different bound experiences.
Stuff you had to learn, like all the examples you gave, isn't "intuition".
Intuition refers to some sort of understanding that arrives without reasoning or evidence.
Very little is actually intuitive. Someone once said that the only intuitive user interface is the nipple. But babies have to learn how to latch on; if it's so intuitive, why do we have breastfeeding clinics?
Humor may be intuitive. Why does a three-month-old chuckle when someone sneezes? Nobody taught them that it's supposed to be funny, or what funny is.
I seriously recommend any programmer to spend an afternoon with FORTH. It gives you a whole new perspective about how to write programs and use computers.
For me, it was a more intense experience than learning Lisp (besides Lisp being really cool!).
Using Lisp changed how I program (so did Prolog and OCaml for that matter). But Forth and APL changed drastically the way I _view_ programming: If we understand it as communicating our intents to the machine using a language, then abstraction should be nothing more but a function of features, performance and the number of tokens employed.
Say you "refactored" our code by implementing a design pattern straight from the GoF book, yet the number of tokens somehow increased? Sorry pal, no approval for your PR from me.
It is the craziest thing, isn’t it, that programs are meant to be both read by humans and executed by machines which operate at significantly different time scales than us?
> Forth is not the language. Forth the language captures nothing, it's a moving target... Forth is the approach to engineering aiming to produce as small, simple and optimal system as possible, by shaving off as many requirements of every imaginable kind as you can.
This has been something on my mind recently: I feel like as a software engineer I spend a lot of time working with abstractions designed to contain complexity, and I really appreciate it when I find the rare few that do so successfully (or get the buzz from having done so myself!).
But there's something even more appealing and satisfying about simplifying the model of the problem so that it's more elegant where that's possible.
The first useful programming language I created was a Forth-dialect in Common Lisp [0].
While understanding Forth was key to even getting me started, since I finally found a thread I could start pulling, something that looked doable from where I was standing; it's pretty obvious I never went all in with the Forth-way.
I've since created several languages [1..] exploring the border between Forth and Lisp, or between control and convenience. And I'm still undecided. Just reading this article about Forth set my mind going in that direction again.
The fact that it's possible to do so much using such simple tools is like a riddle that keeps tickling my brain. And from a theoretical standpoint I find the stack abstraction more beautiful than registers, the same way an ordered set outshines a hashed one; because they're analog, full spectrum, without gaps and extra complexity to cover them.
One of my hobby projects awaiting some free time is an OS. I figure that since Forth is so easy to implement that I can just build a simple Forth implementation for a CPU, then write a Lisp implementation in that Forth — then if I ever want to port my OS, it’s relatively simple.
I think that this would be a nice way to avoid the unsafety issues with Forth: keep the unsafe code compartmented away in the relatively small Forth kernel, while all the high-level stuff is written in a language with sufficient safety guarantees.
I imagine that a Forth purist wouldn’t be terribly fond of that approach. Probably from that mindset a full Lisp implementation is overkill. But from my mindset a full Forth system would be difficult to reason about. Maybe folks who implemented programs in Postscript or NeWS would disagree.
Now all I need to do is retire, inherit a legacy or win the lottery (although first I’d have to play the lottery) …
"explicitly on a stack" in the sense that Forth directly exposes the presence of the parameter stack to a programmer, in contrast to the stack that, say, a C program uses.
"passed implicitly" in the sense that Forth definitions do not require a programmer to explicitly state which arguments are passed in and which results are yielded. (although many Forth programmers provide "stack pictures" in comments by convention.)
The greatest Forth book is Forth on the Atari - Learning By Using by Winfried Hofacker. It’s an old book, published in 1983 in Germany, but the concepts it embodies are timeless. Available as a PDF http://www.atarimania.com/documents/FORTH-on-the-Atari-Learn... but I have an original copy :-)
> The Forth way of focusing on just the problem you need to solve seems to more or less require that the same person or a very tightly united group focus on all three of these things, and pick the right algorithms, the right computer architecture, the right language, the right word size, etc. I don't know how to make this work. My experience is, you try to compress the 3 absolutely necessary layers to 2, you get a disaster.
The other end is the conventional development method where each work in their own silos without a detailed idea of the others. This leads to bloated systems.
I like that article primarily for the chain of insightful comments at the end. I think my conclusion after reading it the first time was that it takes every bit as much time to really "get" forth programming as it does any of the highly opinionated paradigms -- be it functional programming in a pure language like haskell, logic programming in prolog, or true OO in Smalltalk.
The deceptive ease with which you can write your own implementation lulls you into thinking that you really get it when you've written an interpreter/ compiler. But true cultural, idiomatic forth requires a paradoxically deeper understanding than writing the compiler can give you.
I think the author drew and settled his conclusions too soon.
I think the heart of the problem is that the rudimentary ideas of forth- a stack, some stack-shuffling words, some arithmetic, control flow, and that's about it- are appealingly simple, but not enough of the language:
>"I figured I didn't need the more interesting metaprogramming stuff for my first prototype programs, and I could add it later if it turned out that I was wrong. It was wierd to throw away everything I originally liked the most, but I was all set to start writing real programs. Solving real problems in the real world. It was among the most painful programming experiences in my life."
Imagine reading the first chapter of SICP without prior exposure to Lisp, excitedly writing an interpreter for the parts of the language you'd seen so far, and then feeling your enthusiasm slowly slip away into dismay as you attempted to use that stunted fragment of a language to get work done.
Forth can be small, and simple, but the real gems of the language are a bit subtle. The many implications of CREATE>/DOES. Abuses of manipulating the rstack. Striking a balance between parsing words, named locals, global variables, vocabularies, and other tools to minimize twisty stack shuffling. Bending the rules at the right times.