Evan Hahn (dot com)

https://evanhahn.com/blog/

My blog, mostly about programming.

フィード

記事のアイキャッチ画像
All tests pass: a short story
Evan Hahn (dot com)
One night, I wrote a simple tool to pick a random programming language. After shuffling a few times, I landed on Arturo. I decided to try it for fun.What’s Arturo?Best I understand, Arturo is a stack-based programming language. It’s primarily maintained by Yanis Zafirópulos. They published a vision of the language in 2020. Here’s the stated goal from that post:to make something that I myself will use as an easier do-it-all scripting language, you know… automation scripts, templating, latex generation and perhaps help me a bit in the packaging of webview-based applications (think of Electron, but something far more manageable and without having to deal with Node.js and the likes).As a stickler for syntax, I bristle at this writing. That first word, “to”, should be capitalized. In fact, the whole sentence is too long and structured strangely. “latex” should be “LaTeX”.This post, while readable, could be edited for clarity and correctness.Arturo’s website, on the other hand? Flawless! Not
2日前
記事のアイキャッチ画像
Little web app to pick a random programming language
Evan Hahn (dot com)
I wrote a web app to choose a random programming language.It’s very simple; I hestitate to even call it an “app”! The interesting part was scraping all the languages on Rosetta Code, and even that wasn’t very interesting. But I hope you like it!I learned about a language called Arturo this way, and wrote a short story about that experience.
2日前
記事のアイキャッチ画像
human.json
Evan Hahn (dot com)
To quote the human.json Protocol:human.json is a protocol for humans to assert authorship of their site content and vouch for the humanity of others. It uses URL ownership as identity, and trust propagates through a crawlable web of vouches between sites.I think this is a neat idea, so I added it to my site. It’s available at evanhahn.com/human.json.For more, see the human.json documentation. And see how I use AI on this blog.
10日前
記事のアイキャッチ画像
How I use generative AI on this blog
Evan Hahn (dot com)
Inspired by others, I’m publishing how I use generative AI to write this little blog.General feelings on generative AIGenerative AI, like any technology, has tradeoffs. I think the cons far outweigh the pros. In other words, the world would be better off without generative AI.Despite this belief, I use it. I’m effectively forced at work, but I also use LLMs to help write this personal blog. I think they can produce better writing if used correctly.Also: I want to be critical of this technology. Specifically, I want to change the minds of “AI maxxers”, not preach to those who already hate it. If I never used this stuff, AI lovers wouldn’t listen to me. These people are more likely to respect criticism from a daily user who’s sympathetic to the benefits. I think there’s space for critique from a user of a technology they wish didn’t exist.I feel discomfort and tension about this, which I hope comes through.With that, let’s get to the specifics.The specificsMy main rule of thumb: the fina
12日前
記事のアイキャッチ画像
Introducing llm-eliza
Evan Hahn (dot com)
LLM is a popular CLI tool for talking with language models. I built llm-eliza, a plugin to chat with the ELIZA language model.Usage:llm install llm-elizallm -m eliza "I'm worried about computers."# => What do you think machines have to do with your problem?ELIZA, released in 1966, is a state-of-the-art language model. It offers zero-GPU inference with sub-millisecond semantic throughput, and scores highly on EQ measurements (emotional intelligence).Source code here.
16日前
記事のアイキャッチ画像
The two kinds of error
Evan Hahn (dot com)
In short: in my mind, errors are divided into two categories. Expected errors (think “user entered invalid data”), which are part of normal operation, aren’t the developer’s fault, and should be handled. Unexpected errors (think “null pointer exception”) are the developer’s fault, likely indicate a bug, and are allowed to crash.Error handling is an important, but often neglected, part of programming and user experience.Over the years, I’ve developed an opinion about the two types of error in software. This is primarily informed by a career in web and application development, but I hope these learnings are widely applicable.In my mind, errors are divided into two categories: expected and unexpected.Expected errorsExpected errors happen during normal operation. Examples:Validation errors when the user enters invalid data. You can’t control what the user types!Network errors when the user’s network fails. It’s not your fault if the user turns their Internet off or has a slow connection!Pe
23日前
記事のアイキャッチ画像
Notes from February 2026
Evan Hahn (dot com)
Things I did and saw this February.Things I madeI shipped my first feature at Ghost: Inbox Links. When a member enters their email to log in or sign up, we now show a button that takes them straight to their inbox. In addition to shipping a neat feature, I also enjoyed learning about MX records and RFC-compliant email address parsing. The source code for the main logic is here.I was surprised to learn that gzip streams encode which operating system did the compression. I built a little tool, “gzpeek”, to inspect this metadata (and more).The 40th anniversary of the original Legend of Zelda was this month, and I wanted a calendar feed for other game anniversaries, so I made one. Oracle of Ages and Oracle of Seasons just turned 25 yesterday! Speaking of, I wrote a few articles for Zelda Dungeon as usual.Cool links from onlineAn incredible stunt: a game written in HTML and CSS. “No JavaScript or server-side code is used.”Best description of LLMs I’ve seen so far: “When you enter text into
24日前
記事のアイキャッチ画像
Introducing gzpeek, a tool to parse gzip metadata
Evan Hahn (dot com)
In short: gzip streams contain metadata, like the operating system that did the compression. I built a tool to read this metadata.I love reading specifications for file formats. They always have little surprises.I had assumed that the gzip format was strictly used for compression. My guess was: a few bytes of bookkeeping, the compressed data, and maybe a checksum.But then I read the spec. The gzip header holds more than I expected!What’s in gzip metadata?In addition to two bytes identifying the data as gzip, there’s also:The operating system that did the compression. This was super surprising to me! There’s a single byte that identifies the compressor’s OS: 0 for Windows, 1 for the Amiga, 3 for Unix, and many others I’d never heard of. Compressors can also set 255 for an “unknown” OS.Different tools set this value differently. zlib, the most popular gzip library, changes the flag based on the operating system. (It even defines some OSes that aren’t in the spec, like 18 for BeOS.) Many
1ヶ月前
記事のアイキャッチ画像
Track Zelda release anniversaries in your calendar
Evan Hahn (dot com)
The original Legend of Zelda came out 40 years ago today. With other birthdays on the horizon, like Twilight Princess’s 20th in November, I wanted a calendar that showed the anniversary of every Zelda game. So I made one.Subscribe to this URL in your calendar app:https://evanhahn.com/tape/zelda_anniversaries.icsOnce you do, you’ll get calendar events on the anniversary of each game’s release. For example, you’ll be able to see that the Oracle games turn 25 in less than a week…I feel old.If you want to build this file yourself, I wrote a little Python script that generates an ICS file from a CSV of release dates.
1ヶ月前
記事のアイキャッチ画像
Notes from January 2026
Evan Hahn (dot com)
Happy new year! Here are some of my notes from the first month of 2026.New job at Ghost!I started a new job as a Staff Engineer at Ghost this month. According to our homepage, Ghost is “for professional publishers to create, share, and grow a business around their content.” I’m looking forward to building software for independent journalists.This is also the third time in a row I’ve chosen to work for a nonprofit. It’s a pattern now: nonprofits are my default choice of where to work.Things I didlibdeflate does “fast, whole-buffer DEFLATE-based compression and decompression”. I published libdeflate.js, which wraps it up for JavaScript users. Always feels good to use a little WebAssembly.I recently set every single option in my Vim configuration, and blogged about it in “I set all 376 Vim options and I’m still a fool”. Even though I learned a lot setting every flag, I still feel far from mastering an editor I’ve used for almost 14 years. There was some good discussion on Lobsters, Reddit
2ヶ月前