61 comments

[ 2.3 ms ] story [ 115 ms ] thread
This is always annoying to read as they wasted ")" to some shit.

"(" should be: Push next word to X-stack

")" should be: pop and execute top of X-stack.

So "(+ m n)" is equal to "m n +"

And "(IF (< A B) (THEN C ELSE D)))" == "A B < IF C ELSE D THEN"

IF-sentence was totally wrong. Per se.

(IF (< A B)) (THEN C ELSE D) looks about right. This is about readability, all else stays the same. You can avoid the minute overhead of "(" by not using it on a critical situation.

I am not sure what you mean. "(" and ")" as their own words form comments in Forth. As an example:

    (if (< a b)
Would be parsed completely differently from:

    ( if ( < a b )
The first will have the interpreter look up and execute the words "(if", "(<", "a", and "b)". The second will have the interpeter look up the word "(", which will skip all the text that comes before a ")".
Of course we fix the parser too, so that ( and ) are always separate. Otherwise too ugly.
Looks like Lisp, ugh ;)

I guess Polish Notation wasn't as uncommon in the 70's as it is today, AFAIK pocket calculators used this too. And once you switch your mind over it feels just natural.

And once you switch your mind over it feels just natural.

Yet what if the result is, your mind has become unnatural?

!!!

RPN with pocket calculators was nice because of the screen real estate restrictions. But on computers there’s a lot of screen real estate to show the program and the variable assignments to intermediate results. Even with long procedures, it’s easy to scroll, read and understand the execution flow with that extra screen space.
The reverse Polish notation (postfix) is the most natural notation if you want just to compute things, IMO. But if you want to grasp what is going on without computation - other notations can be better for readability.
> "(" should be: Push next word to X-stack

> ")" should be: pop and execute top of X-stack.

> So "(+ m n)" is equal to "m n +"

I don't get it, what is the X-stack? Also can you elaborate this example in more details?

X is separate execution stack. It is very short depending how many brackets you use. When I made such Forth some 50 years ago, the "pop and execute" was one cycle on Nova 1200, no overhead. And x-stack was one 8-bit page.
Thanks. Am I getting right, ( + 1 ( - 2 3 ) ) parses as

    s 
    x +

    s 1
    x +

    s 1
    x + -

    s 1 2
    x + -

    s 1 2 3
    x + -

    s 1 2 3 -
    x +

    s 1 2 3 - +
    x 
which should evaluate to 0?
(comment deleted)
You can certainly override the ( word to replace its functionality. You can even do so late in the compilation process so that the new semantics only apply to the code you write without affecting the rest of the dictionary.

I don't see why you would, though. Even in your trivial example "(IF (< A B) (THEN C ELSE D)))" the brackets are unbalanced and even if they were, IF would be executed after THEN and ELSE. When you push a word to the "X-stack" you correspondingly have to push a word to an analogue of a stack in your mind to know what happens when ')' executes. You failed to do this and therefore your example is broken. In idiomatic Forth, you wouldn't have to worry: in most cases you only have to consider the data stack, and in most cases the sequences you just read to your left imply what's on top of that, not what you read ten words back.

Even if it was slightly easier to read than idiomatic Forth (I disagree that it is), in-line comments strike me as more important "shit" than superficial syntax sugar.

How would it work with more than two arguments?

  (+ 1 2 3)
I discovered Forth when building weather stations with an 1802 8-bit cmos processor; there was a tiny assembler language for it for making games which I adopted to a simple stack-based interpreter, and then I discovered Forth by way of a Byte Magazine piece on it. I started attending Forth meetings in the Bay Area where it was clear I knew from nothing about it, even though I had something similar running. So, I got a set of 8080 assembler codes for Forth and transliterated that to 1802 and the rest is history. From there, I put Forth on an Apple II and found a magazine article which disassembled the graphic and math routines from the Apple Rom; my friend Dan Wood used that to create for us "SciForth" a Forth which did all the math and graphics necessary to analyze data and present it from our weather stations, which, at that time, were being used to locate wind power systems, and for fruit frost prediction in California's central valley.

In the long run, I continued down that path by writing inference engines in Forth. It's a clean and solid ecosystem. Even today, I think about returning to Forth to see how far I can push it.

I wonder what people are doing with Forth professionally these days. I see a lot of hobbyist projects such as porting Forth to a board which is definitely very fun and educational, but not sure what professional Forth looks like. Back in the day people used Forth for programming microprocessors. Are they still doing this?
Does bitcoin script count? Or Postscript?
From what Forth, Inc. and MPE tell about their projects and customers, it seems indeed to be micro-controller focused, but extends sometimes to the desktop. For instance Forth, Inc. talked about a cold storage facility ("a fridge as big as a warehouse") for which they did both the code for the small temperature control devices and the facility monitoring graphical front-end (PC).

    FORTH ?KNOW IF
        HONK!
    ELSE
        FORTH LEARN!
    THEN
There's a soft spot in my heart for ((bumper)? stickers) that only 1/100 of 1% of the population will ever get.
In the 1980s, you could get a replacement ROM that turned the Sinclair ZX81 (aka the Timex Sinclair 1000 in the US) into a Forth machine. It was a fun and affordable way to learn forth at the time.

Forth holds a two unique positions for me: the first developer I met that made over US$100K/year was a Forth developer (25+ years ago). Forth is also the only language where I have met one person who wrote it for a living.

Has anyone had success at seating on a narrowly confined Forth an Isabelle Higher Order Logic for spec. to code proofing a model?
I didn't notice the Jupiter Ace was a thing back in the day, but a while back got the xACE emulator running. I imagine it was a similar experience. Seems like it should be easy to build a code-a-like with an RC2014 or similar system. (And you would have the option of adding a better keyboard.)
Young me would have vastly preferred that to the Sinclair’s BASIC ROM. It would’ve been different from the stuff we were learning at school, but might’ve made that little machine actually useful.
You may be interested in Collapse OS, a "Forth operating system and a collection of tools and documentation with a single purpose: preserve the ability to program microcontrollers through civilizational collapse".

http://collapseos.org

No float/double number support, sadly. Yes, I know "starting Forth" has clues to live with that: https://www.forth.com/starting-forth/5-fixed-point-arithmeti... but I would like at least how to print two ints to make a double.

I tried to implement D+, D-, M+ and such by hand, but they failed.

Neither would the 8 bit CPU you are salvaging. You don't even really need it anyways, you could get away with integer math. You would be running trading algos for bullets and cigarettes in a shanty bazaar.
Someone had made a programmable forth computer in Minecraft. Going back a few years, but I think it was RedPower Mod. It ended up teaching you a little forth to control your factory.
Both forth and lisp seem similar to me. They have a "three sentences to explain how everything works" vibe. Forth uses a stack and so "reverses" the order of things. Lisp uses trees and so "indents" everything. I wonder if there is some kind of underlying rule. If you want "one syntax to rule them all" then it has to be recursive and so there's only a few options: stack, tree, etc. Hmm well recursive isn't the right term here. Maybe somebody who actually has thought about this can correct me.
(comment deleted)
I think the combination of "simple universal syntax" and "utility to human brains to write programs" is indeed probably a relatively small space.

This is in contrast to simply having a "simple universal syntax", and I don't know how many solutions that may have in the abstract sense. There are many cellular automata that from a certain point of view have "simple syntax" (at least in the sense of a limited number of symbols and super limited number of ways to put them together) and have universal computation powers, but are not useful in the slightest for human programming. (Not the most common Turing tarpit to get caught in, but this has snared a number of people over the years trying to turn cellular automata into programming languages.) Who knows what other exotic possibilities may lie out there in math space where no human mind has yet even peered. I think there's probably a lot of other things that are mathematically universal computers, but like cellular automata are just too unstable (in the mathematical sense, all small changes to program produce huge changes to output; we humans prefer languages that have that characteristic only in controlled and limited ways) for humans to program.

And dropping the other criterion of "simple universal syntax" of course reveals a rich space of possibilities, notably including every other programming language that isn't Lisp/Forth/Haskell-esque in theoretically being one of the simple universal syntaxes lifted up to being a programming language. (Haskell is one of the other ones, BTW, being "lambda calculus" reasonably translated to a programming language. It isn't purely so but generally neither is a Lisp.)

It's not an accident! Chuck Moore was a student of John McCarthy before joining the industry.

Forth was created when Chunk applied his knowledge of Lisp to the problem of maintaining a personal library of punched cards which were reusable on whatever weird computer he needed to run them on next.

Is that... do you have a reference for that? (Not challenging, just seeking more knowledge.)
A long time ago I was writing PostScript, C and Common Lisp on the same project - PostScript and Common Lisp definitely have a lot in common.
I've been playing with a language called Joy, created by Manfred von Thun, which seems to me to combine the best parts of Forth and Lisp while being simpler and more elegant than both. I suspect it might be the simplest useful language.

"A Conversation with Manfred von Thun" in Vector, journal of the British APL Association http://archive.vector.org.uk/art10000350

https://hypercubed.github.io/joy/joy.html

Kevin Albrecht’s mirror of Manfred von Thun’s original website for the Joy Programming Language http://www.kevinalbrecht.com/code/joy-mirror/index.html

https://joypy.osdn.io/ (My own project) Here's a flowchart (SVG) for the interpreter loop: https://github.com/calroc/Thun/blob/simpler/joy_interpreter_...

It boils down to quotation as the primary operation, denoted by enclosing expressions in square brackets. Various combinators accept quotes on the stack and prepend (or not) one or more of them to the pending expression under evaluation (like Continuation-Passing Style), and that's it. That's the whole evaluation model.

E.g. "branch" combinator accepts a Boolean value and two quoted expressions and put one of them onto the pending expression based on the Boolean value:

       true [ELSE] [THEN] branch
    -------------------------------
                THEN


       false [ELSE] [THEN] branch
    --------------------------------
                 ELSE

Anyway, I've been messing around with it for a few years now off-and-on and I really think it's "something", eh? (Like I'm almost willing to argue that it's status should be something like the other major models of computation: Turing Machine, Lambda Calculus, SKI Combinators, (Others? Wang Tiles?) ... I suspect Joy belongs on that list.)
Tcl is kinda the same in that regard, hence some expanding that acronym as "try coding less". It's hard to make a powerful language that offers more power in such a small amount of simple, understandable code than these. (Though I have a hard time wrapping my head around Lisp, I find Tcl (and Lua, for a more modern incarnation of the idea) to be dead simple and intuitive, with awesome leverage in capability per LOC.)
You have a hard time with Lisp, but find Tcl intuitive? I'm not judging, just scared and impressed. It's like when my friend told me she found differentiation tricky but integration easy. Objectively that's more impressive, but how?
I think the term you are looking for is "homoiconicity" [1]. There's a trivial 1-to-1 map between the semantic elements the program operates on (Lisp lists of atoms/lists, or Forth arrays of words) and the code.

https://en.wikipedia.org/wiki/Homoiconicity

I was introduced to Froth via [Factor](https://factorcode.org) (which I discovered as a jEdit user as both have the same initial author). Factor is a garbage collected higher order Forth that makes it more fun to program in (example: 'quotations', basically pushing lambdas on the stack). If I am doing coding puzzles I do it in Factor. Some might argue that it's not a real Forth because it's not as close to the metal... but you could rewrite Factor in Forth and then the distinction would be gone (think Lisp reader macros). I recommend people curious give it a try.
Factor is an interesting and opinionated language, I agree that it's worth grokking and playing around with.

I don't consider it a Forth, nor does it need to be. Factor is borrowing from Joy, Lisp, and Smalltalk, the result has a very different flavor. Nothing wrong with that.

The closeness to the metal is basic to the Forth experience, doing interesting things in Factor and in Forth uses completely different mechanisms.

I suggest reading Programming a Problem-Oriented Language[0] by Chuck Moore, because it's among the best memoirs by an influential computer programmer, but also to get a feel for what Forth is all about, what makes it distinctive.

[0]: http://www.forth.org/POL.pdf

I feel obliged to mention Loeliger's Threaded Interpretive Languages. It really helped me figure out what was going on under the hood w/ FORTH. That might be my only "beef" w/ FORTH back in the day, introductory documentation was easy to find, but intermediate and advanced documentation was much harder to come by.

Forth, Inc. now has a number of decent books. Check them out at https://www.forth.com/forth-books/ . And the Internet Archive has plenty of FORTH books: https://archive.org/search.php?query=FORTH . And the FORTH Interest Group has links to most everything else: http://www.forth.org/ .

And let me echo the sentiment that it's delightful to have a programming language you could probably implement in a weekend and understand every bit of what's going on under the hood.

I used Forth professionally on a number of processors over about ten years. On a couple of them I had to implement the language from scratch, including having to write a code editor and other system tools.

Remembering those days always makes me smile. I really enjoyed that work. The language is fun to use, fast to code and execute and as flexible as you want it to be. I made extensive use of it in robotics, including designing and building a networked multiprocessor walking robot controller from scratch. Remember, no Internet, Arduinos or SO; just bare chips, data books and your own creativity.

My first Forth project was on a 6502.

Thanks for sharing, are people still programming robots in Forth nowadays?
I think C/C++ is the popular option nowadays.
> are people still programming robots in Forth nowadays?

Frankly, I haven't kept up with the Forth community. Back in the day it was really popular in astronomy as well. Lots of observatories used Forth to control their telescopes, etc.

The transition to C/C++ was inevitable for a range of reasons. Finding qualified Forth programmers became really hard at some point. For me the transition happened when a friend of mine asked me to help port a Forth codebase to C. The system was used for DNA sequencing by researchers in the Human Genome project.

It had become very difficult to maintain and evolve the product precisely due to not being able to find good (or enough) Forth coders. I think that was the last large Forth project I completed, which, oddly enough, involved abandoning Forth in favor or C.

I also used some Forth professionally. Triangle Digital Services TDS2020 Forth SBCs (Hitachi H8 microcontroller). Also they had a smaller SBC the TDS9092 [1] which I used to turn the bitstream of data from a GPS chipset into NMEA strings.

I wrote Modula-2 on DOS for the data loggers and Forth for the embedded stuff. Happy days.

[1] https://www.triangledigital.org.uk

Forth, and its derivatives, has been the principal language I program with these past few years, but one that is on my radar lately, and I wish I had more of a use for is Joy, a purely functional forth-like language.

In Joy, everything is a function that takes a stack as an argument and returns a stack as a result. For instance, the numeral '5' does not represent an integer constant, but instead a short program that pushes the number 5 onto the stack.

https://en.wikipedia.org/wiki/Joy_(programming_language)

In a real practical application, if you properly evaluate Forth for doing Embedded solutions, then it becomes a real viable option considering the alternatives. First thing is readability of a DSL for an embedded project, working through the HAL that are created just to communicate with the hardware is a real PITA, but forgoing that even further, creating your own DSL for the HW layer is extremely useful even for the HW teams, you can be calling connection the same for once, Pins will be Pins, you will SENDRESPONCE PIN20 etc. Furthermore, you can be doing unit testing with in the development phase not after, so that eases the debugging of the SW and expedites time to do integrated validation. Further more, the interactiveness of FORTH is a unique experience, it makes the little MCU feel like a complete system. There was a recent posting in youtube that best describes this, and IMHO, it’s a hard to beat option as you den with in a MCU, validate each of the function words in Forth to ensure that bit of the code is working. Finally, you don’t need a lot of the dedicated hardware to debug, you are with in the system and you can read the register and memory interactively, so no surprises. If you consider al this, then it’s IMHO a hard option to pass up for this kind of work. Here is the video I mentioned: https://www.youtube.com/watch?v=VPVbARJ8QsA&t=3120s Cheers!
A little-known fact is that the entire preboot environment in Sun's UltraSPARC machines was really just Forth. It was possible to modify that Forth code to do more or different things than what the factory intended, and Sun actually had documentation on how to do that, IIRC.

I really miss having an innovative, open-source friendly hardware manufacturer like Sun around - they were an extraordinary group of people. (I worked for them for a while in the late 90s, and it really was a great company, with by far the best tech-company culture I've ever encountered...)

I share the same feelings for Sun, mourned when it was bought by Oracle.
Back in my university student days, I wrote a pair of a compiler and an interpreter: the compiler accepted a language that looked like a mix of Oberon and Perl (I called it pıpl, from "pıpl isn't a programming language"), it produced Forth-like output, and then the interpreter ran it.

The compiler was written in C+bison+flex, the interpreter was in Object Pascal. Unfortunately, the sources didn't survive.

What is a good modern Forth to play around with?

Is it still used im some industry?

I've mostly only come across in-house tools that have been inspired by FORTH, or used it as an embedded language for company back-end tools.

I suspect gforth is the most common way to get started. Though it has to be said more people probably write forth-interpreters than write serious code using the actual language.

Embedded use might be one of the rare exceptions, as it can be used to give a very lightweight environment.