Evan Hahn (dot com)
https://evanhahn.com/blog/
My blog, mostly about programming.
フィード

How I implemented relative imports with Pyodide
Evan Hahn (dot com)
I was recently playing with Pyodide, the WebAssembly Python runtime. I wanted to have my main code import a utility file. Something like this:# in main codeimport utilprint(util.triple(5))# in util.pydef triple(n): return n * 3This took me awhile to figure out! I’m not convinced I have the best solution, but here’s what I did:Fetch util.py with fetch.Save it to Pyodide’s virtual file system.Run the main code!Here’s what my JavaScript loader code looked like:// Fetch `util.py` sourceconst response = await fetch("util.py");if (!response.ok) throw new Error("Failed to load util.py");const utilSource = await response.text();// Save it to Pyodide's virtual file system.// Pyodide can import modules in `/home/pyodide`.pyodide.FS.writeFile("/home/pyodide/util.py", utilSource);// Run the main code!pyodide.runPython(`import utilprint(util.triple(5))`);This worked for me, but I wish there were a cleaner solution. Maybe Pyodide has a way to hook into import? If you have a better solution, please r
7日前

I made a little audio speed calculator
Evan Hahn (dot com)
I was recently listening to an 8-hour-and-51-minute audiobook, and wanted to know how much time I’d save if I listened to it on 1.5× speed.This math is easy enough; divide 8 hours and 51 minutes by 1.5 to get the new duration: 5 hours and 54 minutes. But I also wanted to:See the final duration along with the time I’d save (with some simple subtraction).Compare different speeds. How much more time would I save with 1.6× speed, for example?Enter the time in plain English: “8 hours 51 minutes” instead of “531 minutes”.So I built a little web tool to do this: the playback speed calculator. You enter a time in English, and you get a big table showing the duration and savings for 1.1× speed, 1.2× speed, and so on.Did LLMs help?This is the kind of software modern LLMs can “one-shot”. You give them a description in plain English, and they produce all the code. And indeed, this was how I built the first version! I prompted an LLM with the app I wanted, and it mostly worked. I had to make a few
15日前

Notes from November 2025
Evan Hahn (dot com)
The months just keep coming, don’t they? Here are my notes from November 2025.Things I publishedComputer-related:I tried, and failed, to make TypeScript immutable by default. I was honestly surprised that nobody swooped in and solved it after I posted this!Watch a recording of my conference talk at Longhorn PHP: “Understanding Unicode”.I took notes on a couple of books this month: Tor: From the Dark Web to the Future of Privacy and The Story of the Typewriter.Video game stuff:I’d long hoped for a sequel to 2003’s Kirby Air Ride. For the past decade or so, I’d joked hopelessly about Kirby Air Ride 2. By a miracle, I finally got it—I just had to wait 22 years. I wrote up impressions of the Kirby Air Riders demo, which was followed by a full release a few days later. Love this new game.And, like every month, I wrote a few articles for Zelda Dungeon. Notably, I participated in the “Retro Remake Rumble”, where I argued that certain versions of games—such as the original version of Twilight
18日前

Draft: Stopping bad guys from using my open source project (feedback wanted)
Evan Hahn (dot com)
Frustratingly, this was a semi-private draft that got posted to Hacker News before I could make edits. I’m leaving the post up as is because it’s already been discussed in this format. But it has a lot of issues.In short: I maintain a sorta-popular open source package, and I want to prevent big corporations and “bad guys” from using it. I want feedback on how to do this.Open source and exploitationI’ve been learning more about open source sustainability. More accurately, I’ve been learning more about how open source is exploited by large companies.Some recent links that have influenced my view:This pair of slides from the maintainer of curl. The first slide: 38 massive car brands that use curl. The second slide: 0 of them give anything back.“The Value of Open Source Software” says that “firms would need to spend 3.5 times more […] if OSS did not exist”, and that OSS is giving businesses about $12,000,000,000,000 USD (12 trillion dollars) for free.“What is open source?” says that “volun
19日前

Notes from "The Story of the Typewriter"
Evan Hahn (dot com)
Project Gutenberg, the free ebook library, has a page that shows you 20 books at random. After refreshing a couple of times, one title caught my eye: The Story of the Typewriter. The book was published in 1923 and covers the preceding 50 years of typewriter history, all the way back to 1873.Though I’m inclined to trust the authority of anyone who maintains a very “Web 1.0” site, I wasn’t interested in an accurate history. Instead, I was keen to see how a 1920s author would write about the technology. Would there be amusing tales? Would there be parallels to my little corner of the world, the computer? The book did not disappoint.Vision impairment comes up repeatedly in the history of the typewriter, apparently. An automatic braille-like machine was “said to have been invented in the year 1784”. The book claims that the first person who could touch type was a “blind typist”. Blindness came up several more times.When people started using typewriters for correspondence, recipients were su
24日前

Experiment: making TypeScript immutable-by-default
Evan Hahn (dot com)
I like programming languages where variables are immutable by default. For example, in Rust, let declares an immutable variable and let mut declares a mutable one. I’ve long wanted this in other languages, like TypeScript, which is mutable by default—the opposite of what I want!I wondered: is it possible to make TypeScript values immutable by default?My goal was to do this purely with TypeScript, without changing TypeScript itself. That meant no lint rules or other tools. I chose this because I wanted this solution to be as “pure” as possible…and it also sounded more fun.I spent an evening trying to do this. I failed but made progress! I made arrays and Records immutable by default, but I couldn’t get it working for regular objects. If you figure out how to do this completely, please contact me—I must know!Step 1: obliterate the built-in librariesTypeScript has built-in type definitions for JavaScript APIs like Array and Date and String. If you’ve ever changed the target or lib options
1ヶ月前

Fizz Buzz without conditionals or booleans
Evan Hahn (dot com)
I recently learned about the Feeling of Computing podcast and listened to the latest episode. One of the hosts challenged listeners to “write Fizz Buzz with no booleans, no conditionals, no pattern matching, or other things that are like disguised booleans.”Here’s my Python solution:from itertools import cycledef string_mask(a, b): return b + a[len(b) :]def main(): fizz = cycle(["", "", "Fizz"]) buzz = cycle(["", "", "", "", "Buzz"]) numbers = range(1, 101) for f, b, n in zip(fizz, buzz, numbers): print(string_mask(str(n), f + b))main()This solution is basically three things put together:Create endless cycling sequences of "", "", "fizz", "", "", "fizz", "", "", "fizz", ... and the same idea for buzz.Combine those two sequences with the numbers 1 through 100 using zip, to get the following sequence:...("", "", 7)("", "", 8)("Fizz", "", 9)("", "Buzz", 10)("", "", 11)("Fizz", "", 12)("", "", 13)("", "", 14)("Fizz", "Buzz", 15)("", "", 16)...Convert the number to a string, then “mask” it
1ヶ月前

"Understanding Unicode": my October 2025 talk at Longhorn PHP
Evan Hahn (dot com)
I gave a talk, “Understanding Unicode”, at Longhorn PHP last month. It’s loosely based on “Why does ‘👩🏾🌾’ have a length of 7 in JavaScript?”, a blog post I wrote in 2023.Though the talk is for PHP developers, I think it’s applicable to anyone who wants to understand more about Unicode, UTF-8, and more.Here’s the recording:Video You can also download the slides here.If you want to learn more about this topic through a PHP lens, see this more detailed presentation by Andreas Heigl.
1ヶ月前

Kirby Air Riders demo impressions (from a big fan of the original)
Evan Hahn (dot com)
Kirby Air Ride patch art by @threadbreak_embroidery Note: the full game is now out. Most of these impressions still stand, but this was about the short demo we got.I like to think I’m a pretty big fan of Kirby Air Ride. I’ve played the game for thousands of hours since its release in 2003. I have a TV in my house hooked up solely to play Kirby Air Ride, which I play at least once a week. I’ve always felt this game was underrated. I yearned for a sequel, but had given up hope after two decades.In April, out of nowhere, Kirby Air Riders was announced. I was floored.This weekend, after what felt like 22 years of waiting, I finally got to try it this weekend. This was in the form of Kirby Air Riders: Global Test Ride, which served both as a network test for the developers and a sampler for players.I played it for hours. Here are my impressions.City Trial: more chaotic, still a roll of the diceThe original Kirby Air Ride presents as a racing game, but any fan will tell you the real treasure
1ヶ月前

Notes from "Tor: From the Dark Web to the Future of Privacy"
Evan Hahn (dot com)
I just finished Tor: From the Dark Web to the Future of Privacy, a profile of the Tor Project. I thought it was an approachable overview of Tor and its history. If you’re interested, the book is free! Or you can read my chapter-by-chapter notes below.Chapter 1: Privacy WorldsThe book claims that Tor “recreates the utopianism of the early internet pioneers, in which many users felt the connective power of the whole internet at their disposal. They experienced a global public sphere that was much harder for governments to control (even if with much of the poison that we see today).”It also talks about how “we write our values into the technologies we build” and how imported technologies “often bring their own cultures with them”. “So if we want to understand Tor and how it has shaped the landscape of online privacy across its history, we might try to pick apart the privacy values of its designers to understand how those values have shaped it over the years.”Chapter 3: Tor’s Strange Begin
1ヶ月前