Viewing Forth
2025-12-15
I’m reading the blog “An attempt to articulate Forth’s practical strengths” and thinking about Forth...
Inheriting Traits From Parent Paradigms
> A side effect of using a parent language is the child will inherit its traits.
Worse, the child will inherit the parent’s paradigm. Usually the parent’s paradigm is restrictive in some way. That’s the whole point of using a paradigm.
The child’s paradigm is different but gets funnelled through and constrained by the parent paradigm.
For example, C popularized the paradigm that all subroutines must be PVR subroutines. This led us into believing in ABIs that insist that all subroutines must be PVR subroutines - Parameterized, Value Returning subroutines.
This implies that every subroutine must expend energy at the beginning to set up the function parameter frame and, at the end, to tear down the frame and set up return values.
With modern compilers, much of this effort is optimized away - but not quite all.
With Forth, this effort is not required for each subroutine. Modern compilers all support the modern ABI and cannot support bare Forth, while modern CPUs do support PVR-less subroutines. Some languages contain the “bare” attribute, which tends to get limited use.
This PVR subroutine paradigm has infected the design of WASM. When one examines the operation of instructions like return_call (opcode 0x12), one can see that it performs a direct tail call to a specific function by unwinding the current frame, then GOTOing the target.
Text Editors As An Exercise
> It is common for Forth developers to create their own rudimentary text editors as an exercise.
One of the first things I did with Frits van der Wateren Lisp (1.5-ish) was to build my own editor.
Threaded Code - Forth vs. Lisp
Forth creates “threaded words” by creating a data structure containing addresses of code to be executed.
The data structure is an “array” - a sequential, packed set of codes that represent other routines.
Forth’s “inner interpreter” interprets the contents of this data structure. The stock one is doCol(). It does a for-loop across the array and calls each routine.
Forth routines are of 2 types:
machine code
“threaded code” arrays.
Each Forth word is an object that contains a reference to the interpreter that is used to interpret its contents. For machine code, the interpreter is the CPU itself (to emphasize: yes, a CPU is just an interpreter implemented in silicon). For threaded code, the interpreter is the routine called doCol(). Others interpreters exist.
Roughly
Lisp 1.5 does this kind of thing also. It stores routines in specific data structures. Eval() interprets this data structure.
The data structure is: lists.
Lisp macros are a way to change the way that code-containing data structures (lists) are interpreted.
Roughly
See Also
Email: ptcomputingsimplicity@gmail.com
Substack: paultarvydas.substack.com
Videos: https://www.youtube.com/@programmingsimplicity2980
Discord: https://discord.gg/65YZUh6Jpq
Leanpub: [WIP] https://leanpub.com/u/paul-tarvydas
Twitter: @paul_tarvydas
Bluesky: @paultarvydas.bsky.social
Mastodon: @paultarvydas
(earlier) Blog: guitarvydas.github.io
References: https://guitarvydas.github.io/2024/01/06/References.html



