One idea that got dropped on the editing floor for this post: the long shadows cast over our lives by the very first systems we program on.
I started programming (in undergrad) on an IBM PC descendant running DOS. I moved on to more sophisticated systems, but over a period of decades keep returning to seemingly little things about that first system that I could never replicate. Little things I turn out to be willing to give up big things for.
For others, it was some game console. NES, GBA, etc. I wonder how common it is to actually escape the gravitational pull of our first systems, how much of the differences between our projects stems from having our brains colonized by different first systems.
The Mu computer's prototyping environment uses traces to explain and debug programs. But traces are expensive to compute and made the environment slow and laggy.
I fixed things by collecting only a shallow trace at first, and iteratively deepening on demand by rerunning programs. This only works because it's safe to rerun functions. There are no side-effects in Mu.
The Mu shell's error handling is now much improved. Errors in programs you typed in were already showing up consistently in a trace without crashing the computer. However, _writes to the trace_ could cause it to crash in cryptic ways. No more.
Now I'm back to my long-term plan: a prototyping environment that nudges people to write tests, so that it's easier to throw away the prototype and rewrite it from scratch. Making codebases rewrite-friendly.
The current implementation is quite naive. Copies one byte at a time, makes several redundant copies per byte. In spite of all that, it makes a huge difference in video quality.
Here's the Bresenham algorithm for drawing circles using a few macros. My current style is to keep line width to 41 characters and lay out two columns of functions.
Caveats:
No nested backquotes yet.
I can't draw circles too far down the screen due to a strange error.
In general, error messages have been a mess ever since I stopped relying
on Linux. A heavy exercise in humility.
With computers, this strategy doesn't work. Inside and outside have a way of switching places.
In Unix, the crown jewels were the root user; other user accounts were sandboxed. Code (in C) ran all types erased.
Time passed. Root grew vestigial, people stopped sharing computers. The crown jewels moved to user accounts.
Some possible lessons to draw from these sample points.
Sandboxing isn't about a single boundary. When designing VMs for adoption, build for isolation within the VM in addition to the boundary. Allow people to collaborate and run untrusted code within a single sandbox.