As you learn Forth, it learns from you (1981)
jupiter-ace.co.uk
jupiter-ace.co.uk
https://thinking-forth.sourceforge.net is worth reading, even if you have no desire to ever program any Forth.
- Build up the thinnest abstraction that lets you express a solution in the problem domain.
- Allow the API user to express their intent, and not be focused on mechanics they don't need to understand to get the job done.
- Focus on getting the interfaces right before the implementation is perfect.
- A clean interface will allow you to make drastic changes to the implementation without the API consumer becoming aware.
Paul Graham has described lisp as a tool for writing fast programs fast (that's the gist at least). IIRC, he clarifies that each fast is a phase. Lisp allows you to write a fast, high level, prototype that might have poor runtime performance and then you refine the prototype so that the compiler can generate fast machine code.
Forth is similar but feels closer to the machine than Lisp because of the stack based threading model. In Forth, you often don't need manual memory management _or_ garbage collection and you can easily extend the system with new low level words. But it does require you to think differently about your program design so that it fits the stack based vm model.
Historically, Forth has been implemented in assembly but you can write a Forth that targets any host. The truly mind expanding thing is that you, an individual, can write a Forth compiler and you can also write it in such a way that it has multiple targets. For example, you can generate native, jvm and js targets from the same underlying source. Usually this can be done by translating the forth generated AST to source code for another high level language. This allows you to write a fast high level language quickly without getting bogged down in writing, say, fast x86 codegen or a garbage collector. To get started, you just target the host language with the best high level properties that you need (which will be problem and context specific). I don't enjoy writing c, but I have no problem translating to c if I need to for performance or for syscall access.
To illustrate the practical power of this. Suppose that you have an important subcomponent of your system that was written in, say, Node.js. It turns out that this is a critical bottleneck that cannot easily be optimized in javascript. You don't want to rewrite the whole system, but you do want to rewrite that component and have it seamlessly interoperate with the existing system. You could write a small Forth DSL for that subcomponent. This Forth will target javascript initially. You translate the subcomponent into Forth and reuse all of the existing tests (that were presumably also written in javascript). Then you rewrite the tests in Forth so that the entire subcomponent is now written in Forth. Now you write a new backend that translates to say, c or rust with node bindings. You can run the native implementation against a native implementation of the test suite since they're both written in high level Forth at this point. Then you can flip the switch between the native or javascript implementations and be confident that both implementations are identical because they have the same high level description.
Once you start seeing things this way though, you start realizing that you can write Forth style code in any language (and the reverse is also true). Forth is as much about a process for solving programming problems as it is a specific, concrete language. This is also why there is the old adage "once you've seen one Forth, you've seen one Forth."
(Moved to 6502; don't recall having a version for that.)
Factor might be a counterexample if one considers it a Forth, the VM is in part implemented in C++: https://github.com/factor/factor
I think it's portability and ease of development rather than CPU architecture complexity that makes someone pick C/C++ over assembly when implementing a Forth system. Because the Forth won't need much of the assembly language or obscure CPU instructions, the complexity of the architecture won't really matter to whoever is implementing it.
I'm absolutely not an expert, just a long time enjoyer of some classic Forth books and certain concatenative languages.
Also ...ycombinator isn't exactly just a community run bulletin board either. Although HN not being ad infested is absolutely amazing. Also the simple design.
Sure, I'm not really using this as a web forum, I'm not here for the community.
I certainly get that itch sometimes after the person at the coffee shop asks me if I've downloaded the app for the 50th time. No, I don't want 45 apps on my phone just so I can get a tiny discount or a free coffee each year.
Regarding the comment on asking friends. I think that has some value, but it assumes that you know someone for everything you're interested in or that they have the same kind of purchasing power or ideas as you. The Internet can be helpful there if you're interested in the best bang for the buck for a newbie, or the best product period once you've spent more time.
However, most weekends I travel to the forest with my family and we spend some time walking, cooking and hanging out in a distinctly analog setting.
No, it doesn't. It assumes they might know someone who knows someone that has valuable input. Doesn't require that they have direct experience either, it's usually enough that they have adjacent experience. And then there's books, when _I find myself to be the unique snowflake in my social network there's always someone who wrote a good book or more on the topic. By now my physical library is quite large and covers a large portion of occidental modernity, both fiction and the sciences.
The Internet is nice and all, and sometimes there's good advice in contemporary web forums, but it's also pretty young and lacks both the depth and width of the last few centuries of dead tree storage. These days people also throw second hand books after you if you say you're interested, or they charge a euro at most unless it's something collectors might find valuable.
I quite enjoy computers and computer networks, though. It's mostly the social and entertainment industrial side of it that I find unsatisfying.
The amount of lost bits of information makes the explanation totally worthless, even though you technically can explain it. The point is it's a waste of time. You won't understand LSD, Beethoven or Forth until you have tried them.
However, the Forth experience and reading about legends like Chuck Moore (at least for myself), just gave me this feeling that most of our problems come from software bloat and having these infinite abstraction levels where nobody ever truly understands what in the world is going on anymore. Such a system is ironically more efficient from a developer's perspective (at least until you run into weird bugs and edge cases) as developers just basically glue together libraries and only need surface level understanding to get something running. Another option might be to design your own hardware and then a simple forth system on top of that which exactly solves the problem and nothing else. The implementor would have laser level understanding of the design choices. Of course, there are other issues such as how to maintain such a unicorn, even if it is beautiful and elegant. Today, we have lovecraftian horrors with huge swaths of people working together to keep all the abstraction levels working together and hope there aren't any leftpad incidents.
In my industry we do a lot of optimization and the standard technique is to not reinvent the wheel and to use a solver (e.g. Gurobi) where you give the silver your decision variables and constraints and have it quickly return the optimal decisions. This is great, but costs a lot of money (the best solvers are almost entirely commercial) and you treat a core part of your program entirely like a black box and you also have to fight things like the license manager and so on. Another option is not to create your own generic solver that solves all problems, but rather a solver that solves just your problem. The one company I know that does this has been enormously successful and their product is incredibly fast and lightweight with zero dependencies besides Windows (really cool). The only negative is that now the application is tightly connected to his own solver and they can't just switch it out easily with a different one like most people can. It's all a set of tradeoffs at the end of the day.
s/infinite abstraction levels/Rube Goldberg contraptions/
All those abstractions are necessary in order to do software engineering of real-world systems at scale. Forth lets Chuck Moore put something together quickly in very little code, that serves Chuck Moore's needs adequately well, but... Chuck Moore isn't the average person, let alone the average developer. Chuck Moore doesn't need, for example, a file system; why have one if you can just memorize the sector numbers for everything on disk?
A lot of the "bloat" in modern computing consists of things necessary in order to make computers tractable for ordinary people. This is as true for things like Electron[0] as it is for C and conventional operating systems vs. Forth on bare metal. And if technology doesn't work for people, it doesn't work.
[0] Electron has enabled a Cambrian explosion of cross-platform apps by vastly reducing the time and effort it takes to develop such an app. Developer effort is often the costliest part of software; by that metric, Electron has probably saved billions of dollars, despite consuming hundreds of megabytes that would otherwise be wasted anyway.
No, they're not.
You cannot make engineering decisions based on "it'll change how you program." There are several concrete examples of turning imperative code into pure monadic code that contains less boilerplate and is less noisy with Haskell's do notation. Exhaustiveness checking, encoding invariants in types, those all have good examples that one can read and agree or disagree with. Surely there are concrete examples that one can give about Forth too?
Writing C code feels like writing a rule book, writing java feels like designing a lego set, writing lisp feels like writing proof, writing prolog feels like writing puzzles. Writing forth feels like writing a dictionary, then after that you write a few sentences. They're different feeling, but forth is one of the most flexible as you can go up and down from the most basic units to the high level ones. As another comment has mentioned, you can program forth where the basic units are elements from another language, and construct a dsl/dictionary out of it. Then switch the basic units while retaining your business logic for a faster implementation without a full rewrite.
> I wish I knew what to tell you that would lead you to write good Forth. I can demonstrate. I have demonstrated in the past, ad nauseam, applications where I can reduce the amount of code by 90% percent and in some cases 99%. It can be done, but in a case by case basis. The general principle still eludes me. -- Chuck Moore
https://www.ultratechnology.com/moore4th.htm
You might appreciate other quotes from the above page.
Language is a very lossy compression algorithm, and some concepts aren't even computable in the first place (i.e feeling and emotions)
Was it actually possible, back then, to make a living selling Forth for CP/M computers? Or Assemblers? Did Stackworks have an office, with a jaded-looking middle-aged secretary who put out her cigarettes in an ashtray on her desk, before she picked up when the phone rang? A glad-handling salesman who came back to the office every few weeks before going out to sell?
I don't think it has been possible to sell a compiler which isn't a loss-leader in a bundle for what, 30 years?
Or were these side hustles? Alan Ashley, was his day job being a math teacher or something, and he did this to round out his budget?
The industry was a heck of a lot smaller back then, but these old articles mention way more different companies. Seems like before all these behemoth monopolies there was a lot more air to breathe.
The '70s and early '80s, it was CP/M, TRS-80, Apple ][ software. By the mid '80s and into the early '90s it was all one-person shops that were making custom UI controls for Windows 3.1. Tree and list controls were popular, plus some database connectors. By this time there were small companies making C++ libraries to make Windows programming easier, I remember Zinc and Zapp. They were wiped out when Visual C++ came out with Microsoft Foundation Classes.
The alternative is a world where developer tools are expensive, and thus only the rich can program their own computer.
I agree and personally feel that this is unfortunate and that we are in some ways imprisoned using mediocre to bad compilers by our collective refusal to pay for better ones.
because of tooling, large code bases, and weak standardization they had a huge amount of lockin. and only a single narrow funnel in which to address deficiencies.
and while certainly on a lower tier than EDA seats, werent super cheap. they usually had limited platform support. while they did optimize better for their targets, otherwise they were poorer systems than gcc, with all its warts.
And the ones made by corporations were prohibitively expensive. As a teenager wanting to learn, or a hobbyist making programs for fun, would you really pay $4500 for a compiler to tinker with projects in your spare time? There's one reason hardly anyone uses Delphi anymore. By the time they finally released a Community Edition, there was no community left that had grown up learning Pascal.
Mine got modified quite a bit over the next couple of years. Extra RAM. Some dumpster diving got me several keypads with good quality keys. I took them apart and made a proper keyboard to replace the original dead rubber monstrosity.
I made a parallel I/O port out of TTL logic and veroboard. And then temporarily my Ace rode about on the top of a fairly flaky micromouse exploring mazes. It didn't win any prizes but it did get me an A in O-level Technology.
My school was throwing out an old teletype, so I scavenged that. Then I modified the parallel I/O port to output +/- 12V on one pin, and wrote software to bit-bang RS232 at 110 baud. Back before the Internet, just finding the specs for RS232 was not so simple - our local library was a bit limited in that way - but I got there in the end. A lot of guesswork and trial and error. I don't think anyone made a printer for the Ace, so I may have had the only one. Being able to print code listings really helped.
The first summer I wrote a whole load of games, mostly in Forth, but sometimes Forth just wasn't fast enough. I got a copy of "Mastering Machine Code on Your ZX81", and learned Z80 machine code. If there was an assembler available, I didn't have it, so this was all hand-assembled. Getting jumps right was a total pain, as was debugging. Generally, it either worked first time, or you started from scratch again. Usually I got there in the end.
I sold those games through a ad in "Your Computer" magazine, and earned back the price of the computer several times. But recording and shipping tapes one at a time got tedious really fast, so I didn't take that any further.
Somewhere over the years, with my parents moving house multiple times, the Ace disappeared. Many years later, I found one on Ebay, and still have it. But somehow I never fell back in love with it - it just wasn't as good as I remembered my one rather non-stock one being at that formative time in my life.
The good old days, before layers of 'protection' got baked in (Apple II vs Mac).
Steve Vickers, one of the founders of Jupiter Cantab, was my university lecturer back in the 90s. He taught a very obscure course in mathematical structures, and in a sense was both the first and last (a decade and a half later) to teach me computer science. Previous comments: https://news.ycombinator.com/item?id=23760382 https://news.ycombinator.com/item?id=26375986
There are kits out there to make your own though:
https://www.tfw8b.com/product/minstrel-4d-turbo-jupiter-ace-...
https://www.ebay.com/itm/115272079823?itmmeta=01J10WB15JY1KF...
These docs support that: https://docs.oracle.com/cd/E19455-01/816-1177-10/816-1177-10...
The system supports FCode, which is processor-independent byte code. This allows expansion devices (like a card or peripheral) to bring with them their own platform-independent device drivers, which is pretty cool. So you could make a disk controller card and then any system that you plug it into could boot off it, no matter the CPU architecture.
Anyway, the point is, since it was mainly used for booting and diagnostics, I don't think they put much effort into performance. For it to be an actually good Forth environment, I think you'd want to have some way to run Forth programs as native code, either by adding the option to JIT the FCode instead of interpreting it or by adding a compiler that compiles Forth source to native.
Also, I believe the old PowerPC Macs (like G3, G4, and G5) used Open Firmware, so if you wanted this Forth experience, you have that option in addition to Sun workstations.
So did the OLPC-1 where the non-FOSS nature of "Open" Firmware was a bit alien.
Still, stop-a and then e.g. 3719 824 + 53 * . when you needed a little bit of arithmetic help was always a possibility ;)
(It might be easier than finding an old Sun machine)
They sold Jupiter Aces. Wish I had the money back then to get one!
I always start out defining the ideal API I want to solve a problem and then solve the problem using the not-yet-implemented API. I then implement the API recursively by adding lower level API’s that makes it easy to solve the higher level API problem. And most of the time I already have a lower level API from a previous project I can easily reuse and perhaps expand.
So I don’t start with the database moving towards the biz logic. I start with the biz logic moving towards the DB (if needed). It works really well.
I think this is similar to how experienced Lisp developers work. Starting out defining a new “language” (a bunch of functions) that makes it easy to solve the problem and then recursively implementing it. However I work in C++ and Typescript not Lisp.
https://www.stephan-becher.de/strongforth/
FORTH compilation is typically minimal (bit of a defining feature really), so there is no static (i.e. compile-time) type verification or much any optimization.
O.t.o.h., the JVM is stack-based and has been used for a plethora of programming languages, many statically typed.
The JVM is stack-based and static typing rather common in the languages that runs on it.
Factor has dynamic typing, though I haven't thought much about that, it kind of stays in the background. It's more a tool for problem solving than a description of some type theory: https://factorcode.org/
Don't really see the point, though. Static on-the-nose typing tends to shine when a lot of people need to do quick edits to large amounts of code, settings where code is never done, and that's not exactly where Forth-like languages are a good fit. They're more for settings where few people think long and hard and experiment a lot until the right solution is found and then it's done, I think.
In practice I often find the shape of data to be good enough and don't feel a need to also put names to it. It might be convenient to invent a type to carry some constraint, like UserNicknameString that can only be up to 200 4 byte characters (or whatever the big emoji chars in Unicode are) and no more, but that can also be solved functionally. As far as I'm aware no one has yet created a serious ERP or social media product in a Forth-like language, so maybe the perks that come with having an ontology of ten thousand types keeping things in check are still illusory for the hardcore forthers.