Programs Are Sequences of Opcodes
At the hardware level, a “program” is just a sequence of opcodes.
Repetitive Sequences
It was noticed that some sequences of opcodes were the same.
Machines didn’t care about the redundancy.
Humans wanted to reduce the amount of memory that was u$ed.
Human programmers, also, cared about redundancy and wanted to use principles of DRY - Don’t Repeat Yourself.
The Concept of Subroutines
So, CALL and RETurn opcodes were invented and implemented.
This made it possible to write a part of a script only once and to re-use that part several times.
The trade-off was that these opcodes added inefficiency to programs.
CALL and RETurn opcodes took measurable amounts of time to execute.
Another trade-off was that programmers had to reserve a part of memory to store bookmarks. We call these bookmarks “return addresses” now.
Hence, the concept of subroutines came into being. Subroutines are pieces of routines that are subordinate to the main routine. Such subroutines are like inlining that is performed at runtime at a cost CPU cycles.
Compilers, today, perform some inlining at compile time, thus, making programs run faster since they don’t incur the CALL/RETurn opcode cycle overheads. The trade-off with compile-time inlining is that more memory is needed. People didn’t want to expend memory in the early days, but, today, we have become accustomed to using huge amounts of memory and this cost is essentially hidden from programmers.
Another cost is that subroutines are sequential and that the main routine needs to suspend (aka “block”) when invoking subroutines. That is considered OK, since the main routine is usually sequential anyway.
Sequentialism, though, is causing problems, now that we have begun using computers for non-sequential programs, like internet, robotics, IoT, etc. Programmers have been forced to suffer gotchas like callback-hell and have invented ad-hoc workarounds like await, which are used to help convert sequential programs into state machines.
The Concept of Functions
At some point, the word function began to be used to describe the routine-subroutine behaviour. This word - it’s only a word - caused people to think that code is like mathematical functions and had the same properties as mathematical functions.
This use of the word then caused the introduction of all sorts of restrictions to make code work more like mathematical functions. A lot of the restrictions were only glued onto the paradigm after problems - gotchas - were noticed after-the-fact. A glaring example of this kind of ad-hoc approach was the invention of priority inheritance which came about due to the Mars Pathfinder fiasco.
As far as I can tell, the concept of program functions was invented early on, but, was greatly popularized by the spread of the “C” programming language.
Before “C”, FORTRAN had two words for what was going on - SUBROUTINE and FUNCTION.
BASIC expressed these concepts in a different way, using the GOSUB and the DEF keywords.
“C”, though says that every routine is a function.
State Machines
The concepts of state machines were known long ago, even before programming was invented.
The main problem with state machines is “state explosion”.
Around 1986, David Harel wrote a paper describing StateCharts that showed a syntax that tackled this problem to the ground. This was a “structured programming” approach for state machines. Unfortunately, hardware of the day was incapable of inexpensively implementing this syntax.
The programming community continued using only caveman syntaxes based on grids of non-overlapping, small bitmaps called characters based on Gutenberg type-setting ideas.
Today’s hardware can handle better syntaxes for programming, but programmers continue to use caveman syntaxes anyway. The concept of programming languages based on characters has led to a different kind of explosion, akin to the state explosion problem. Today’s programmers blithely speak in terms of huge amounts of memory, like Mb instead of Kb. Bloat in software goes unnoticed and remains essentially hidden. We do need more memory for storing richer visual information, but, we don’t really need wildly fatter subroutines for manipulating that information.
See Also
References: https://guitarvydas.github.io/2024/01/06/References.html
Blog: guitarvydas.github.io
Videos: https://www.youtube.com/@programmingsimplicity2980
Discord: https://discord.gg/65YZUh6Jpq
Leanpub: [WIP] https://leanpub.com/u/paul-tarvydas
Gumroad: tarvydas.gumroad.com
Twitter: @paul_tarvydas
Substack: paultarvydas.substack.com