Before domain-specific languages (DSLs) and REPL environments (read, execute, print, loop) became fashionable, computing pioneer Charles (Chuck) Moore had built, by 1968, what he viewed as the perfect computer programming language, which he named FORTH (for fourth generation language). What he had kept in view during its creation was an extreme austerity in syntax and structure as he searched for the minimalist system required to interact with a computer and be able to write custom problem-oriented languages to solve them. This approach is what he considered to be “programming”: you solve your problem by developing an application specific language with multiple levels of abstraction giving you in the end a small dictionary of simple words (in code) which represents the solution cleanly and in overall the fewest lines of code. Let’s look at this idea, how it has worked out over the years, and how you can apply this, regardless of the language you choose to (or have to) work with. This article looks at Forth, Lisp & Ruby, language that make it easy to solve classes of problems by writing your own DSL, i.e. by programming a specific “problem-oriented language” in which to solve your problem.
1. Succinctness is Power
Paul Graham, the well-known founder of Y Combinator, wrote “Succinctness = Power” in 2002. A few quotes are noteworthy:
“[Power] is directly proportionate to succinctness. Certainly succinctness is a factor in readability, in the mathematical sense [that] total effort = effort per line x number of lines. (We have to be careful here to distinguish between the readability of an individual line of code and the readability of the whole program. It’s the second that matters.)”
“To the user encountering the language for the first time, a programming language that has high readability-per-line means that the source code will look unthreatening. … [But] this is similar to the very successful technique of letting people pay in low monthly installments instead of frightening them with a high upfront price. [But] installment plans are a net loss… the buyer is going to make a lot of those low, low payments; and the [similarly] programmer is going to read a lot of those individually readable lines.” (Paul Graham, 2002, Succinctness is Power)
Larry Wall, creator of Perl, says something similar when talking about Java, in his 2013 interview: “Java is sort of the Cobol of the 21st century … It’s kind of heavyweight, verbose, and everyone loves to hate it … But managers like it because it looks like you’re getting a lot done. If 100 lines of Java code accomplish a task, then it looks like you’ve written 100 lines, even though in a different language, it might only take 5 lines. It’s like, you can eat a 1-pound steak, or you can eat 100 pounds of shoe leather. Though you feel a greater sense of accomplishment after the shoe leather, maybe there’s some downsides.” (Larry Wall, 2013)
What of Python? Paul Graham again: “Python’s goal is regularity and readability, not succinctness.” (PG/2002).
2. Lisp… and Forth
So what is more concise and more powerful? Paul Graham’s destination is Lisp, and he describes why in “Revenge of the Nerds“: “Lisp was a piece of theory that unexpectedly got turned into a programming language.” (PG/2002b) Or, to expand a bit, Lisp is more powerful and succinct than most modern languages because it was developed as math, not as a language. Its designer, John McCarthy (MIT), came up with it as a simpler form of a universal Turing machine, but did not imagine it would be implemented: his graduate student Steve Russell wrote it later in IBM 704 machine code.
If Lisp is good, then Forth is better. All the power of Lisp, due to its extensibility and recursiveness, all of this has been consciously built into Forth by Chuck Moore, who learned Lisp and APL from McCarthy at MIT, programmed with Fortran at SAO, Algol at Stanford, and Cobol at Mohasco.
Where Lisp is the embodiment of an academic paper, Forth” is the working toolset of a master programmer, a programmer with a severely minimalistic mindset, and who has been sharpening his toolset for 40 years: it took Chuck 10 years to invent Forth (1958-1968), another 10 years to perfect it for writing software only applications (1968-1978), after which he pursued software into silicon with Forth chips and other MISC (minimal instruction set) chip designs (some, like the Novix, used by NASA for space satellites), tighter and sharper Forths which he used to build his own CAD tools for doing ultra efficient chip layouts, until finally arriving at ColorForth in the 1980s. He tinkered with this through until July 2001 (the last stable version), and which he has now used for 18 years, including for use in the 144-multicomputer on a chip, the GA144 super Forth chip.
But, back to the title heading:
Here is what Chuck Moore has to say about Programming a Problem-Oriented Language:
“I’ve written many programs over the years. I’ve tried to write good programs, and I’ve observed the manner in which I write them rather critically. My goal has been to decrease the effort required and increase the quality produced.
“In the course of these observations, I’ve found myself making the same mistakes repeatedly. Mistakes that are obvious in retrospect, but difficult to recognise in context. …
“I’ve also been distressed at the lack of concern from others about problems I consider significant. It amounts to a general indifference to quality; a casual attitude of confidence that one’s programs are pretty good, in any case as good as necessary. I’m convinced this confidence is misplaced. Moreover this attitude is reinforced by the massive trend to high-level languages and a placid acceptance of their inefficiencies. … [To counter this, there is] a Basic Principle and two corollaries: Keep it Simple, Do not Speculate, and Do it Yourself. …
“I’m going to tell you how to write a program. It is a specific program; that is, a program with a specific structure and capabilities. The next step is a problem-oriented-language, [i.e. one that is] tailored to a particular application ([one can] substitute application language as synonymous.)
A problem-oriented-language can express any problem I’ve encountered. By permitting the program to dynamically modify its control language, we mark a qualitative change in capability. In a sense, our program has evolved into a meta-language, [i.e. a language which] we apply to the application.” (Chuck Moore, 1970b, Programming a Problem-Oriented Language)
He then he goes on to describe, from first principles, why Forth is built the way it is, i.e. it is built to be the ultimate problem-oriented language, complete in 4K bytes of code. (Note this is indeed bytes, not K bytes or megabytes!)
What are other examples of problem-oriented languages? There are many, but almost all of them are static, i.e. not extensible. Only Lisp and Forth have that capability of extensibility (meta-language) out of the box.
Forth, by its design, makes it easy to write a domain specific language. No need to decide on a syntax or write a parser. The Forth engine is the parser and uses the dictionary which your program dynamically extends with the new domain specific vocabulary.
3. Domain Specific Languages
Looking at domain specific languages generally, examples are: graphviz, CSS, regular expressions, SQL, and parser-generator tools. These have a syntax not limited by any specific programming language, but as a consequence, one needs to treat it with a parser.
What about writing a DSL in an existing language (not Forth)? In this case “you have a particular idiomatic usage of one programming language; you’re still writing in that host programming language, but you’re using only a subset of its features, you use it in a kind of pidgin way to get that same feeling as you have with an external dsl. What you want to get is the feeling that I’m programming in a language that has been specially written to write my kind of state machine, even though you are programming in the host language, for example Ruby. You still want to fool yourself with the illusion.” (MF/2013) Martin Fowler Fowler/2013 (28:40)
This is at the heart of what a problem-oriented language approach is.
4. Programming in a Problem-Oriented Language, and a Plug for Forth
Why have we gone on this journey through history and languages? Because programming to build problem-oriented languages (or domain specific languages) is, I believe, is at the root of productive application programming, regardless of the language you choose to use.
Quietly, many have chosen to work in Forth, some exclusively, and others as detoxification from a software development world which is anything but simplistic or minimalistic. (See Scot Stevenson’s article, How I came to join the underground computer cult of Forth, (Feb 20, 2014).
Forth is a language that forces this type of thinking upon you, and it is worth using until the way of thinking has become ingrained, second nature. Then one will write in this way in any language, for the better.
Bernd Paysan puts it well:
“Forth is an interactive language… You have a command line and you can just type commands in and try them out. This is very helpful for the beginner and the impatients, and it turns out that it is helpful for everyone, especially for debugging. You don’t need to write a test program to test your program.
“Forth is fast… Though it has an interactive command line, programs are really compiled to quite efficient code. Forth programs are also called “words”, since each program has a name … You call it just by typing in that name. There is no difference between words from the language and words you defined yourself, you can even define words using an inline assembler. The whole system is written this way.
“In this respect, Forth is quite similar to Lisp and its descendants… [but] Forth differs from Lisp in that it doesn’t use lists, neither for calling, nor for storing multiple values. Forth uses a stack to pass data between words, and it uses the raw memory (as seen by the assembler programmer) for more permanent storage. It’s much lower leveled than Lisp, and that’s one of the reason why it is fast. It’s not only fast, the simplicity makes it very small, too.
“Forth is the ultimate language for building extensions. Programming in Forth is generating higher levels of abstractions, until you have a language well fitted to solve your problem. The simplicity of the underlying system allows it to rely on it, which is important when you search bugs. The usual approach for application programming is to keep each layer simple, too. This is essential for rapid development of critical applications.
“Forth is said to be an amplifier. A good programmer programs better in Forth (and he learns to program better in other languages, too, when he masters Forth); a bad programmer programs worse in Forth, and he’s spoiled when working with other programming languages.” – Bernd Paysan, Why Forth?, 1997
Jeff Schilling writes similarly:
“One of the unique things about Forth (at least until the resurgence in interest in Domain Specific Languages – fueled by Ruby but arguably around for a long time) is the ability to have the source language converge on the problem space. It is a magical place wherein the syntactic sugar of the programming language fades into the background and the language of the domain emerges.
“Many experienced Forth programmers have reported that the language frees them to think in terms of the solution instead of the tool, that it is expressive enough to encourage original, elegant solutions without penalty and without bending over backward. (Some have even said their use of Forth made them better programmers in other languages.)” – Jeff Schilling, The Joy of Forth, 2007.
5. Invitation
If you haven’t tried Forth, try it. Start with Starting Forth and GForth, or with F-PC Forth within vDosPlus (an MS-DOS emulator for modern Windows machines). You may be surprised at how much it starts to grow on you, and to change how you think about applications programming.
To see the results of using Forth to build real applications, check out my Turtle Logo program with installer and source code included. It was written in 2016 in about 900 lines of Forth code using F-PC with the main program development done in spare time over a number of weeks, and then extended into a full fledged program for pre-schoolers to learn programming concepts over the next several months (my first child was the first user). To my surprise (and delight), coming back to it three years later for my second child, it was easy to continue to extend it again with minimal effort due to the tightly factored design that Forth steers toward, and the multi-layered, problem-oriented language that results.
For an example using Ruby, see the Cuneiform Transliteration Parser and Sign Frequency Generator built to analyze the first known instances of writing in Uruk and Susa c.3500 BCE (nearly 5500 years ago!). Watch this space for that article (forthcoming).
Related Articles
- Six Areas of Computer Programming: A Survey
- Applied Propositional Logic: A summary of the theory, a simulator in 28 lines of Forth code, and digital design using only NAND gates
- Forth Reference
- Coding for pre-schoolers: a ‘Turtle Logo’ in Forth
- The Mathematics of Uruk and Susa (c.3500-3000 BCE)
- Experimenting with Microcontrollers – an Arduino development kit for under £10
- Voice-controlled Hardware: Making Sensors Talk for Under £5
Further Reading
- Scot Stevenson, How I came to join the underground computer cult of Forth, (Feb 20, 2014)
- Why Forth? By Bernd Paysan, creator of GForth and GForth for Android
- The Dragon-free Internals of Forth, Scot Stevenson, (May 17, 2014)
- The Joy of Forth: Rediscovering our past, Jeff Schilling, 2007
- Forth postings, Scot Stevenson, 2014/2015 posts
- Programming in Forth – Books from Forth Inc. (many free)
- Forth Library on Amazon
- Arduino Controlled by eForth, C.H.Ting, 2018, PDF available for free. Explains how Forth lets you learn a chip interactively – bare metal programming!
- Forth with Life (integrated Mobile/Cloud medical application).
- Charles (Chuck) Moore (b.1938), Father of Forth, and Stack-based Computing. Wikipedia.
- [Moore/1970a] Forth: A Language for Interactive Computing, Chuck Moore, 1970, PDF download
- [Moore/1970b] Programming a Problem Oriented Language (POL), by Chuck Moore, 1970, (PDF download)
- [Moore/1991] Forth: The Early Years (History of Programming Languages), by Chuck Moore, 1991. In it, he describes the 10 years it took for him to invent Forth (1958-1968), between MIT’s Smithsonian Astronomical Observatory (he knew John Gaustad, took a course from John McCarthy on LISP, and had looked at APL), Stanford, and Mohasco.
- The Evolution of Forth, Rather, Colburn, Moore, 1993
- CISC vs. RISC vs. MISC, MuP21: A High Performance MISC Processor (MuP21 = MISC Microprocessor 21) C.H. Ting & Chuck Moore, 1995
- The Continuation of Chuck Moore’s Journey in search of Computing Nirvana (my title, Jeff Fox’s main page of Ultra Technology)
- Forth-79 standard
- Forth-83 standard Word List Summary
- ANS-Forth 94 standard
- Threads of a FORTH Tapestry, Byte, August 1980, Editorial
- Go FORTH and multiply!, 1981 article
- The Many Forths, Survey by Jeff Fox. TinyMicros Forths
- Forth Chips, Survey by Jeff Fox. FIGnition DIY computer for £20 on Ebay
- A 3-instruction Forth
- GreenArrays Technology, GA144 – 144 full-fledged processors on a single chip. People
- 22 patents (Moore Microprocessor Patent library)
Can you provide a link to the Cuneiform Transliteration Parser and Sign Frequency Generator?
Could be of interest in the context of digital cuneiform analysis:
1. Analyzing Handwritten and Transcribed Symbols in Disparate Corpora, and
2. Multi-Scale Integral Invariants for Robust Character Extraction from Irregular Polygon Mesh Data
Hi Enki, thanks for sharing your papers on using pattern recognition for automated drawing and transcribing of cuneiform tablets. Cool stuff!!
To explain what I’ve built:
Assuming that (a) the signs in the raw clay have been identified already (by a human or your program), and (b) a transliteration has been recognized for these signs, then the sign frequency generator can provide the distribution of individual signs with the transliterated text.
It does so by scanning a transliteration downloaded file from the CDLI database which contains the set of tablets which are desired to be analyzed.
If this is in line with what you’re looking for, drop me a note and I’ll share the sources ahead of the article that is in preparation on this topic.
Assad-
Interesting read.
Just to note, Forth and Lisp are not the only ones to ‘do it’ out of the box.
Tcl is the third major language that has exactly the same properties.
Meta-programming is the Tcl idiom and it has more in common with Forth than Lisp does.
Homoiconicity appears to be the key word here.
Simon, you’re right, TCL is indeed another relatively simple language that makes metaprogramming easy. Amongst languages built for meta-programming (power), if we measure simplicity as the extent to which syntactic sugar (parentheses, braces) is required in the language’s specification, then TCL appears to be perhaps on a par with Ruby, with Forth the simplest that I am aware of (the only syntactic sugar is whitespace). Thanks for the comment!
And thanks for the interesting article, although, I hope you’ll forgive me if I suggest that:
It’s highly questionable whether simplicity is measurable through syntax alone (if it were then Smalltalk would belong in this article).
Forth is certainly simple to ‘parse/interpret’, but there is, even according to Chuck Moore, some reasonable debate as to whether this makes things harder to comprehend as a result. It’s a trade-off.
The real power-through-simplicity (beyond implementation) is found because all words can be arbitrarily composed and because it’s essentially typeless and point-free. The latter being, I would suggest, far more significant.
Of course, there’s also a little sleight of hand, in that Forth does have symbolic words, that operate the same way as ‘syntax’. ‘:’ and ‘;’ for example. I agree it’s a somewhat blurry distinction, but nevertheless Forth does require a few words that serve the same syntactical purpose as you’d find in Lisp or Tcl.
Also, it’s worth noting that Tcl has slightly less syntax than Lisp. You could get by in Tcl with nothing more than whitespace {}, “” and [].. even the $ sign is only sugar for the ‘set’ word/command, much in the same way ‘:’ or ‘” is used in Forth.
As Tcl is itself a DSL of sorts, it, (similar to Forth), has no actual commands, control structures, logical operations, or in fact, anything at all. There is, like Forth, no core language directives. Ultimately Tcl is (at the theoretical level) *only* syntax / convention.
Tcl’s notion is commands – Forth has words; strikingly similar. The only real difference is prefix vs postfix notion. (and of course, both Forth and Tcl can support the other n-fix, trivially, and do so.)
Prefix is simpler to implement, but is it simpler to work with than postfix? ( I really don’t know)
It’s the stack that really separates the two.
Forth uses white space, Tcl uses \n to separate words and whitespace to separate values. (hence the need for {})
It should also be noted that braces in Tcl, do not serve the same purpose as in other languages. They are still part of the ‘text’ of a program, all they do is prevent substitution. They do not, for example, describe block structure as one might find in C, or in () in Lisp.
Tcl and Lisp *could* be argued to be simpler (meta-programming) languages because they are both homoiconic, Tcl perhaps the simpler of the two. Forth is not, and this is makes meta-programming a tiny bit harder. Tcl is certainly much simpler, and more internally consistent and much nearer to Forth than Ruby.
There’s a lot of nuances in all of this.
And finally, implementation. Given what I said above, Lisp is of course relatively complex compared to the other two.
Tcl however, could be implemented as trivially (more so even) than a Forth. A handful of syntactic rules, and a basic command / fetch / execute loop, and you would have a mininal Tcl. The fact there is a canonical implementation of Tcl, is just an accident of history.
But, maybe Forth just has the edge there.
As for Ruby, nice language, though it is, it’s not even close to these three, syntactically or semantically. Surely it’s in the same broad group as Python, and has an entirely different objective. A decent scripting language, but lacks much of the above.
Overall though, I can only agree with your general positive conclusions about Forth.
Simon, thanks for the detailed analysis. Yes, you’re right, if we consider : and ; in Forth, these are indeed syntactic sugar elements corresponding to brackets in Lisp.
I’m particularly intrigued by your comment on the ease of Tcl implementation. One of the attractions of Forth is that it is a relatively small language that can be implemented natively onto a microcontroller, after which one has no need in most cases for any other development tool or operating system and can rapidly prototype functionality within Forth itself. Presumably then Tcl should have a similar application…
And indeed (courtesy of Google):
ParTcl minimal interpreter
Tcl integrated with special hardware
Small TCL for hardware constrained devices
TinyTcl for embedded applications
Tcl and Arduino
I had not had Tcl on my radar for embedded control applications — thank you for the insightful observations! Will be exploring this in the near future.
Assad-
[…] mathematical linguistics), biology (chaos theory, self-organizing systems), economics, finance, linguistics and fuzzy logic, and […]
[…] 8: A low-level toolchain for x86: NASM (Netwide Assembler) and TCC (Tiny C Compiler) Chapter 9: Language-Oriented Programming: Forth, Lisp, and Ruby: Languages that enable solving your problem in …. Part 3: The Embedded Stack Chapter 10: Microcontrollers, Sensors, and Embedded Systems: Low-Cost […]
[…] assembly language, while retaining the efficiency and elegant design of a high level language or domain specific language (DSL). Forth is lightweight, has some incredible capabilities, can be used for both low- and high-level […]
[…] expansion through Domain specific language (DSL) capabilities. The full expansion capability of a Forth or a […]