Neptune → Triton
I would classify a lot of my side-project entirely-for-fun programming as "doodling". I'll get an idea (from a user's perspective), and I'll want to see how it feels (as a user). So I'll get to work spiking out an implementation. Sometimes these implementations take a few hours and I can tell quickly whether the ideas actually work well in practice. Other times, they're good enough builds that I can tell that the UX or general ideas are decent, but would require significant effort to perfect to the point of being a viable product or full feature. And many times, it takes me weeks to work through a problem and come up with a usable test.
I call this process of mine "doodling" to properly frame the goals of these projects. I'm not intending to build a full product. I'm not spending this time in hopes of gaining enough Monthly Active Users to support myself and family. I'm not working on the side like this with the goal of reaching funding or acquisition. None of those are my goals; instead, my goals are entirely to have fun and let my programmer's mind wander into realms I don't usually get to for work.
As such, if I've painted myself into a corner with a particular problem, eventually it ceases to be fun. At that point, I'll often shelve the project for the moment and focus on something else. I'll usually return to the project, but almost always as a rewrite from the ground up with the intention to avoid the major pitfall from before. This is certainly an inefficient process, but it's the one in which I find the most joy.
All of that to say: I've found myself stuck in Neptune after quite a bit of work. A few issues with it (totally skippable content you find the specifics uninteresting):
- The auto-refreshing UI is slow to re-render. Conceptually, I can imagine how to cache bits of the interpreter to speed things up significantly, but have been less interested in improving efficiency at this time. I'd deferred this problem in two ways:
- I added a CLI frontend to the interpreter that accepts a file as input and prints an output that's visually similar to the UI (a split pane with outputs on the right side).
- I added a preference to the UI app to pause execution and only re-interpret on command.
- I stuck with my preferred way of handling units, unit definitions, and unit relationships too steadfastly. I ran into massively inefficient unit conversions and never got the conversion between units' dimensionality to work.
- For unit conversions, the interpreter had to walk the tree of possible conversion outputs until finding the target. It's been a little while since my CS classes, but I think this was a breadth-first search with no care taken to inefficiencies.
- "Units' dimensionality" doesn't quite seem like the right phrase, but I'm talking about converting between length/area/volume (where the kind of dimension is the same (distance) but the quantity of that dimension is different between units).
(2 cm * 3 cm * 5 cm) + 20 mlshould output either50 cm³or50 ml, because 1cm³ is convertible to1ml. The way Neptune's inefficient unit conversions worked, this would involve synthesizing many unit conversions, further slowing down the interpreter.
- I leaned into multiple use-cases of the language from the start – this set a positive stage for things, but it led to complex work later on. I began with two data types: rational numbers and strings, then shoe-horned booleans into strings, then added lists and dictionaries as containers.
- Most of the interesting work in Neptune was surrounding units and their conversions, but these didn't apply to Strings at all. Anytime I'd deal with handling types in the interpreter I would have to also handle Strings despite often not caring about them.
- Of course, for the final product I'd want to hand Strings and Booleans around, but these weren't necessary for my primary focus.
- I wanted the language to be fully lazy, but I started off writing it as an eagerly evaluated language. It turns out that this is a tough transition to make.
Enter: Triton
"Triton" is the largest moon of Neptune, so I felt like it was a good name for a follow-up doodle.
In Triton I'm starting by narrowing my focus to deal with the issues I previously had:
- fully lazily evaluated
- the data types available are Rational Numbers, Lists, and Dictionaries
- no unit handling logic
- no UI App, only a CLI