Now, for something completely different ...
Computing and programming are two completely different disciplines. Historically, for the past 50+ years, we’ve been conflating the two disciplines into one.
Computing is the idea of converting every problem into an equation, no matter how many hoops one must jump through. Mapping computing onto hardware is akin to the invention of FFTs for mapping analogue into the digital domain. This is interesting, but, it is not the be-all-and-end-all of programming.
Programming is the idea of designing re-programmable machines, then exploring what they can do (which is much more than just being used as compute-ers). We’ve had programmable machines for centuries - we have known for a long time how to make machines in machine shops with gears and levers, i.e. to program/create machines using materials like wood and metal. The invention of re-programmable machines is something new, though. We have designed machines that can be re-purposed, easily, to accomplish very different tasks. Instead of machining new parts, we can twiddle some knobs and switches and cause the underlying hardware to act differently. One aspect of Remics is figuring out what the common, re-purposing operations are, another aspect is brainstorming the invention of new machines for different purposes, another aspect is to figure out how best to express “programs” so that they contain enough detail to run these new-fangled machines while expressing to other humans why certain programs are composed in certain ways, or, at least how to maintain provenance between two completely different expressions of the same goals, i.e. using more than one “programming language” per project - one for machines, another one for humans - with some sort of bond between them.
For in-depth study of the workings of reprogrammable electronic machines and for the alternate study of compute-ing, I would suggest:
to teach sequencing of operations, and, worrying about low level data types like bytes, int16/32/64, floats, doubles: teach simplified assembler (MC6809, NS32016, VAX, PDP-11, ...)
modern CPU architectures are much too complicated for an introduction
bonus: you can show how to implement "concurrency" and multi-tasking and coroutining in about a page of code (ch. 10, esp. pg. 229), (one might emphasize the fact that the word “concurrency” as used in programming (conflated with compute-ing) does not conform with the dictionary meaning of the same word)
to teach mapping of mathematical thinking onto CPU-based hardware: teach Lisp 1.5, Sector Lisp, etc.
modern "programming languages" are much too complicated and embellished with too many doo-dads to reveal the fundamental principles
modern "general purpose" programming languages are just embellishments of assembler, i.e. most PLs are just variations on how to think in terms of sequential, imperative operations. Most PLs just map "pure functions" onto sequential, imperative thinking
C is a disaster, it doesn't have garbage collection, it has wannabe macros, it conflates mathematical-ish functions with CPU-ish subroutines driving one away from the actual principles of CPUs, encouraging one to learn how to only map math onto CPU-based machines, i.e. how to compute instead of how to program. Too many niggly details need to be addressed before anything actually works in a C program.
Javascript is a disaster. The defaults that are built into Javascript result in horrible debugging headaches, e.g. it doesn't even vehemently count arguments to functions (aka “arity”, regardless of more complicated concepts like typing of arguments)
to teach paradigms: sample Smalltalk, Self, Forth, Prolog, Tiny Basic, Lisp, Racket, Scheme, Rebol, Drakon, StateCharts, relational programming (Prolog, miniKanren, datalog, etc.), DSLs (REGEX, BNF, OhmJS, etc.), garbage collection vs. manual memory management (Blue Book and early Lisps show how to implement heap-based GC, while Sector Lisp shows how to implement FP-based GC).
to teach how to lift one's head off of the desk: building cheap-and-dirty compilers like SmallC (DDJ Vol. 5, pg. 176), interpreters and garbage collectors like Smalltalk Blue Book (Part Four), OhmJS, purer-than-pure Functional Programming: Sector Lisp
to teach game programming: teach understanding of core-level principles, teach brainstorming and creativity, then teach how to read walls of documentation
to teach internet-ing, robotics, IoT, etc: teach understanding of core-level principles, plus understanding of "free will" and protocols, then teach how to read walls of documentation
to teach hard-core, but modern programming: Odin (Zig, maybe? I know nothing about Zig, except that it competes in the Odin space, which is a new-and-improved C space. Odin is much better than C, IMO)
to teach massive parallelism: explain in detail 1972 Atari Pong (no CPU, no code), or how LLMs work (good luck), or how Quantum Computing works (good luck)
To teach “do one thing well”: Software Tools.
If it's not obvious, I think that modern computing obfuscates the very basics of what goes on inside a computer, especially after 50+ years of embellishments and bauble-adding. I suggest that the basics of how CPUs - just bags of transistors - can be composed into things with interesting properties, should be taught first. Once the basic principles are understood, show how the plethora of existing programming languages can save effort when working with these properties.
I think that the important things to learn are:
how to create sequential recipes, and how that differs from creating asynchronous recipes
what paradigms (not languages, which are just syntactic skins) have been discovered and could help in solving problems.
Furthermore, I think that learning this kind of stuff can lead to inventing the future of programming. The future of programming can follow at least 2 paths:
more of the same, with incremental improvements and more baubles
something with new interesting properties (substitute "bags of transistors" with "bags of computers", in the above).
PDF Version
See Also
Email: ptcomputingsimplicity@gmail.com
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