And whereas it must, of course, be the task of the historian, archaeologist, and prehistorian to show that the myths are as facts untrue -- that there is no one Chosen People of God in this multiracial world, no Found Truth to which we all must bow, no One and Only True Church -- it will be more and more, and with increasing urgency, the task of the psychologist and comparative mythologist not only to identify, analyze, and interpret the symbolized "facts of the mind," but also to evolve techniques for retaining these in health and, as the old traditions of the fading past dissolve, assist mankind to a knowledge and appreciation of our own inward, as well as the world's outward, orders of fact.
"he knew better than to allow his countrymen to be stoked up after his departure from Paris [to the Italian theatre]. Angry that the newspapers there were claiming he had predicted he would capture Milan within a month, he wrote on May 19, ‘That is not in my character. Very often I do not say what I know: but never do I say what will happen.’ 12 He ordered that ‘a jocular note’ to that effect be inserted in the [state-controlled newspaper] Moniteur. In fact, he was indeed in Milan within a month of leaving Paris."
As a Marginal Revolution reader, I wanted an Android App. Then one day I realized, wait a second, I'm a programmer -- why not just make one myself? I couldn't think of a good reason not to, so I did. It went better than expected, and resulted in Fractional. Here are five reflections on the process.
The 97.5 Percentile
Libo, my sibling, was home for the holidays and recommended I use Flutter (a UI framework built on top of Dart) after having AoDict turn out well (as I confirm in the reviews). Having never done Mobile, I was in no position to disagree.
Bloom's 2 Sigma Problem is the observation that, in comparison to traditional learning, an average student with 1:1 tutoring performs 2σ better. In other words (assuming a normal distribution) those tutored students achieved at the 97.5 percentile level. For me, even though Flutter has many strengths (see the next section) I strongly suspect that it was Libo/I being together in the same room and their willingness to help that caused things to go well.
On top of answering more basic questions, Libo more importantly introduced new concepts I didn’t know I didn’t know. For example, I spent a long time trying to manually find an Element that fit what I now know is a selector, but then Libo taught me that there was a built-in. Although at a literal level Googling "Dart query selector" would've been easy, that's missing the point; my unfamiliarity with selectors meant I lacked the vocabulary to Google it in the first place.
One day, Libo asked how helpful I thought they were. I joked that "every time we talk saves an hour", but now I'm not so sure that's a joke. Bloom’s 2 Sigma Problem apparently applies to learning programming too. Unfortunately, 1:1 tutoring currently doesn't scale, but I remain hopeful.
Before the many upsides, let's start with a few downsides. Though the installation process was pretty well documented, I did have to Google a couple of things. But hey, who told me to use Windows. As far as the language itself, there wasn’t much to complain about. I guess it's somewhat unfortunate that inside print() Strings can't be concatenated with "+", but no real complaints. Of course, the simplicity of my problem space surely hid other downsides, as well as my general lack of Mobile knowledge, i.e. I don't realize something is subpar because I've never known a UI framework that did things better.
On to the good parts. In recent times I've mostly used C++, which is a short way of saying I've spent a lot of time wishing things compiled faster. In contrast, Flutter has hot reloading. This means loading new changes is as easy as opening the Flutter terminal and pressing a single button, as opposed to C++ where adding a logging statement takes multiple minutes to recompile. Admittedly, the C++ codebases I'm using are multiple orders of magnitude bigger, but I suspect the relative efficiency of hot reloading only increases with codebase size. C++ does have plenty of other virtues though.
The standard paradigm to populate data in UI frameworks is seemingly to call backend APIs. However, for my use case there wasn't an API, so even though I didn't know much about the DOM beyond its existence, I needed to do HTML parsing. Since that's not part of the standard paradigm, it's unsurprising that Dart's available tooling was much worse than Beautiful Soup, for example. This meant I had two issues: not only did I not understand the DOM, I also didn't understand Dart. As I've used Python before, to divide and conquer I first used Beautiful Soup to understand Marginal Revolution's DOM before reimplementing the needed functionality in Dart. This way I didn't have to deal with both issues at the same time. This method felt useful, though I won’t be able to A/B test until someone invents a time machine.
Fractional also uses a bevy of open source libraries. This has all the expected benefits, but one unexpected benefit of those libraries was that they didn't in turn depend on a bunch of other custom libraries, which meant that I could directly inspect my dependencies to figure out what was happening. More generally, open source was so effective it's not clear I did much at all, as evidenced by the app being <500 lines of code. There's a Gen-Z joke here somewhere, but regardless, a testament to Flutter's power. Flutter also remains under active development, and will be releasing features including, to name but one, Static Metaprogramming.
Time flies when you're having fun, and the 20 hours spent coding over five days felt like a Cessna joyride. In the past I've been too easily distracted, so I wanted to try my best to avoid distraction. Even avoiding 10% would've been a win, and although being mindful wasn't super effective in the past, my plan was to be...super mindful. I succeeded entirely. Yes, that confused me too. Don't get me wrong, I was happy to code without getting distracted, just confused as to how it happened. Yet now that I think more about it I shouldn't be, because there wasn't much to keep mindful about. The hidden factor? Hot reloading, because it drastically decreased the potential time to be distracted. On the other hand, during small-medium C++ recompilations there's much more time to be distracted, which is why I intentionally try to avoid alt-tabbing to avoid paying the cost of context switching. Succeed sometimes. In any case, I still believe mindfulness is most of the battle. The rest was probably that I made Fractional for myself. Creating it for myself both motivated me and also implicitly prevented feature creep because I didn't need a ton of features.
Speaking of mindfulness, something I should've been more mindful about was avoiding negative work. One day I spent 5.5 hours coding in the afternoon. That night I was in a good mood, so I did another hour. But I shouldn't have bothered, because almost all the code from that night had to be deleted. Worse, I was too tired to have the mental presence to discern what should've been kept, such as handling italics. Oops.
Is about the nicest thing you could say about my design skills. When I took drawing lessons as a kid, I was so bad that my teacher moved back to China. Okay maybe that was a coincidence, but for a long time I've thought that design isn't my thing. For Fractional this wasn't worrying because Marginal Revolution itself is relatively minimalistic, so the only other place where design might matter is app iconography (e.g., for the Play Store), and Flutter apps already have default icons. Well, not worrying until I learned you’re (generally) not allowed to use the default iconography.
I'm skeptical about the claim that only the “special” can learn programming. I believe a lot in people's ability to learn, programming or otherwise. Luckily, Fractional didn't need to be very complicated, so while there were many ways of outsourcing, I decided to stop being a hypocrite and start learning design. And though reaching design's upper echelons, like anything else, probably requires something more, I managed to come up with
It ain't centered, but it's honest work.
New Year's Resolutions
One of mine is doing side projects this year. Just like it was one year ago, and two years ago, and also every other year since I started programming. True, Fractional was actually written in late December, but that's nothing Git can't fix. New year, new me?
Use the repeated flag -e. For example,
grep -e foo -e bar myfile.txt
searches for lines in myfile.txt with either foo, bar, or both in them.