Lately I’ve been trying to learn Terraform so I can create and manage cloud resources in a more repeatable and less error-prone way than futzing around manually in the AWS console. Terraform focuses on creating infrastructure according to a given description of the desired end state, and though it has facilities to run scripts on your compute instances after they’re created, this doesn’t seem to be encouraged. Instead, you can pass a shell script (or other supported cloud-init directives) that will be executed when the compute instance starts for the first time.

Because there are typically some limitations on what can be passed in a cloud-init script (most notably a size restriction), I wanted to make my cloud-init script as minimal as possible, and put the bulk of the configuration/bootstrapping code in a script fetched from S3. This turned out to be a relatively straightforward process once I figured out the plethora of AWS objects that needed to be created.

Lucy Merriam recently put together a collaborative spreadsheet to track NYC city council members’ positions on defunding the NYPD. I put together a little web app that lets you look up your council member’s position, contact info, and public statements. For example, here’s speaker Corey Johnson’s position.

Under the hood, this uses a Google Places widget to look up addresses, the NYC Geoclient API to look up representative information for each district, and the google-spreadsheet package to fetch information about each representative from the collaborative spreadsheet. Initially, the rendering code was just a big template string, but now I’m using Vue to make data binding simpler and less error-prone.

The source is on GitHub here.

Because I have a number of friends who enjoy wordplay and are huge nerds, the concept of Levenshtein distance—the number of single-character deletions or insertions necessary to make two strings match—comes up in conversation more frequently than you’d expect. This prompted me to put together this little app (source) a while back, which lets you visualize the edits required to turn one string into another.

I love the phrase “much ballyhooed”: I even used it as my Twitter bio for a while. Does anyone ever use any word besides “much” before “ballyhooed”? Has anything ever been described as “occasionally ballyhooed”?

A couple of days ago, I was working on a web server, and I got stuck on the “tell the server to listen on localhost:3000” step. Why was I using port 3000? For local development, it’s a meaningless and arbitrary choice. That got me to wondering: what port numbers do others choose use when developing software?

Once again I find myself trying to learn Haskell. I’ve given up on this multiple times in the past, in no small part due to tooling issues: why is Stack trying to download so many different versions of GHC? why can’t I ever get any IDE-like functionality to work properly in Visual Studio Code?

I asked for advice from the Haskell community at the Recurse Center, and ended up deleting all my existing Stack/Cabal/haskell-ide-engine/Homebrew/??? installs and following this guide instead. The instructions were mostly correct, though a couple of things have been renamed or updated. For the sake of completeness and my own future reference, here is what I ended up doing to get a working development environment:

My only computer right now is my MacBook Air, a 2013 model. I recently upgraded its internal storage from the impossibly-cramped 128GB SSD that it came with to an aftermarket 1TB NVMe drive from Crucial. (That’s its own whole saga; this thread is the definitive resource on how to do this.) While this has been working decently well for a couple of months, I’ve started to get increasingly frequent kernel panics related to the storage drivers. So, naturally, I decided to install Linux (Ubuntu 20.04 LTS) and see if that worked any better.

Any website born after 2017 can’t blog. All they know is Hugo, charge they phone, S3, CloudFront, Lambda@Edge, eat hot chip, and lie.

A few days ago I wanted to find a dataset with a list of winners of the Palme d’Or. The table on Wikipedia wasn’t formatted in a way that would be easy to copy, and I figured this was as good a time as any to figure out how Wikidata works.

Wikidata is a Wikimedia Foundation project that aggregates structured information about the world. It stores and retrieves facts based on an item/property/value system. Items are nouns, like Parasite. Properties define a relation, such as “award received” or “director”; they also specify another item as the value associated with that property, like Palme d’Or or Bong Joon-ho.

Wikidata provides a public query interface that uses a query language called SPARQL. No relation with Spark: it’s actually running on a graph database called Blazegraph. The query language works on a sort of fill-in-the-blanks basis with the item/property/value triples.

For example, to see which awards Parasite won, you can write a query like this: