What follows is my interpretation of the concept of “substrates” in Jonathan Edward’s keynote[1] at the Live 2024 conference. All misinterpretations and errors are mine.
To me, "substrate" means "pure paradigm". Early PLs, like Prolog, Smalltalk, Lisp, Forth, function-based PLs1 are just syntactic skins draped over pure paradigms. The current software “Stack”, though, has been created by the injection of carcinogenic impurities into such pure paradigms, instead of having been created by building on top of the pure paradigms.
We (the royal "we") have mostly focused on injecting impurities into only one of the pure paradigms - the function-based paradigm (currently called 'FP').
Sector Lisp[2] is a modern throwback that shows what can be done by keeping FP pure2. Sector Lisp - an example of pure functional thinking - does not have mutation and can’t be considered to be a full solution to the problem of programming hardware. That doesn't mean that mutation needs to be injected into Sector Lisp. It means only that pure FP ain't "enough", hence, more than one paradigm needs to be used for programming real hardware.
CPUs are the antithesis of the pure functional paradigm. CPUs are fundamentally based on the concepts of mutation and control flow and memory sharing. Draping pure FP over top of CPUs obviously creates useful results, but, that's only part of the whole story.
If one insists on thinking that a CPU is a substrate, then one must consider that all first-layers built on top of the substrate are of equal utility, e.g. FP (context-switching, function-based paradigm) ~~ Prolog ~~ Smalltalk ~~Lisp ~~ Forth ~~ BASIC, etc. etc.
Building on top of a substrate means "building on top of it" instead of "shoving features into it".
IMO, the next step in building on top of FP is the idea of macros (text-to-text transpilation).
Instead, we see a tower of complexity that stretches the FP substrate out of its sweet spot, that has been created by injecting anti-FP concepts into the function-based paradigm. Anti-FP concepts like mutation, heaps, exception control-flows, etc., have been liberally injected into so-called general purpose programming languages.
FP, at its core, is about stacks. Heaps are but an aberration relative to FP-think and have led to overly-complicated solutions for concepts like garbage collection. Within the pure FP paradigm, GC can be couched much more simply.
Is there a substrate that CPUs are built upon? Yes. VLSI.
VLSI is built upon a substrate of ICs3.
ICs are built upon a substrate of transistors.
Transistors are built upon a substrate of complex molecules of various kinds of rust ("oxides").
Molecules are built upon a substrate of atoms.
Etc.
Do CPU opcodes tinker with the fundamental internal structure of VLSI?
No.
Opcodes are a use of VLSI, and not an attempt at modifying the internals of VLSI.
Do modern programming languages tinker with the fundamental structure of their substrate paradigms (like FP)?
Yes.
Are 1950s approaches to solving the time-sharing and memory-sharing problems of insanely expensive CPUs appropriate for 2024 problems of choreographing very cheap, and plentiful, CPUs?
No.
Modern programming languages are composed of cancerous ideas injected into otherwise clean substrate paradigms and have created an overly-complicated Stack, instead of a clean evolution of one (or more) pure paradigms. The Mars Pathfinder[3] software crashed on Mars because of whack-a-mole synchronous concurrency issues. But,,, we forged ahead anyway and are now playing whack-a-mole with asynchronous concurrency (randomness, irreversibility, ordering, etc.). Callbacks failed to be convenient-to-use. Complicated contortions like promises, futures, .thens, etc. have been injected, in whack-a-mole style, into function-based PLs.
I’m not advocating that we pull the plug and start all over again. We need to find ways to incorporate what we’ve got as we move forward. Knowing more about “what we’ve got” is useful knowledge, though.
See Also
Leanpub WIP
Twitter: @paul_tarvydas
Bibliography
[1] The Meaning of LIVE from
[2] LISP with GC in 436 bytes from https://justine.lol/sectorlisp2/
[3] Mars pathfinder disaster from https://guitarvydas.github.io/2023/10/25/Mars-Pathfinder-Disaster.html
C, Pascal, ALGOL, etc. These all require the addition of an engine that supports context-switching - commonly called an “operating system”. Much like the idea of Lisp machines, these function-based engines are supported by baubles added to the underlying hardware, e.g. MMUs, protection rings, etc.
Sector Lisp fits the whole language into 436 bytes. The garbage collector is only 40 bytes long. Sector Lisp is written in assembler. On the surface, it might appear that Sector Lisp is so small because of assembler tricks, but, there’s more going on behind the scenes. The fact that Sector Lisp guarantees the use of pure functional programming makes it possible to architect the garbage collector in ways that are not possible when using a heap. At the bit level, pure FP works in a stack-based manner instead of in a random-access manner. This means that the GC can be optimized in ways that a heap-based GC cannot.
Integrated Circuits