Posts in "programming"

I wrote a little Python web chat thingy ages ago, Seshat. I haven’t touched it again in over 15 years. Someone asked me for permission to re-use that name on PyPI. I’d refuse under other circumstances — supply chain attack, anyone? — except that I strongly doubt there’s a single user of my package anywhere. The new person wants to rename their legitimate, long-lived project in a completely different niche so there’s no chance of confusing the two, either.

Because of all that, I’m agreeing to it. They’re starting the transfer process and I’ll approve it. If you’re the one person in the world using my abandoned project 15 years on, please consider vendoring my code. In fact, you can flat-out have it. Call it your own. Put it under your own license for all I care.

In short: some time after March 2026, the Seshat name on PyPI will start pointing at something else.

For giggles, I added a new Rust implementation of Little Fluffy Clouds so that you can use it as a standalone binary. The Python version isn’t going away! It’s still the only solution I know of for merging lots of IP networks quickly and correctly.

github.com/kstrauser…

PHP: Not exactly bad, but still a strange one

PHP is so hard for me to describe. I used it a lot in the late 90s when we were migrating off mod_perl because it was a great way to add dynamic data to otherwise static pages, and no one really knew how to develop large sites yet. We were making it up as we went along. But ye gods, the language was bad. “A poor craftsman blames his tools” and all that, but imagine a screwdriver with 2 handles and 3 tips projecting at random angles. Sure, you could assemble an IKEA desk with it, but would you want to? And would you look suspiciously at anyone who claimed to love that weird screwdriver when the equivalent of a Snap-On was available for free from the same place they got the weirdo?

I think that’s the root of much of the horror. No one would bat an eye at using PHP to add little bits of server-side content here and there. It’s great for that! But then you see the giant castles of non-Euclidean horror built with it, and people pointing to them and saying “see what you can make with that weird screwdriver?”, and parts of the castles randomly fall off and kill their owners. No! While that’s impressive, it doesn’t exactly inspire confidence in the screwdriver, or in the people who keep using it to build things larger than it was clearly able to do well. But heaven help you if you point out that there are saner screwdrivers. “You’re just being close minded and out of touch! We added another handle to it and removed the razor blade so it’s much better now!”

Maybe so, but wow, it’s still one hell of an odd screwdriver.

I'm coming around to AI-assisted programming

I’m working on a personal project where I saved some initial programming time by hardcoding a lot of configuration, like:

let board_menu = Menu {
    name: "Board".to_string(),
    help_suffix: "B".to_string(),
    commands: vec![
        Command {
            arg: "B".to_string(),
            help: "Board list".to_string(),
            pattern: make_pattern("b"),
            available: available_always,
            func: board::board_lister,
        },
        Command {
            arg: "Bn".to_string(),
            help: "Enter board #n".to_string(),
            pattern: make_pattern(r"b\s*(\d+)"),
            available: available_always,
            func: board::board_enter,
        },
        ...
    ],
};				

I wanted to turn that into a config file so that other users could tweak it without editing code or having to recompile. I opened a new file in my editor which I had connected to GitHub’s Copilot free tier, saved it as “config.json”, and pasted the Rust code into the file so the AI would have something to look at. I started typing:

{
  "menus": {
    "board": {

Then I paused for a second. Copilot came up with this autocompletion:

{
  "menus": {
    "board": {
      "name": "Board",
      "help_suffix": "B",
      "commands": [
        {
          "arg": "B",
          "help": "Board list",
          "pattern": "b",
          "available": "available_always",
          "func": "board::board_lister"
        },
        {
          "arg": "Bn",
          "help": "Enter board #n",
          "pattern": "b\\s*(\\d+)",
          "available": "available_always",
          "func": "board::board_enter"
        },
        ...
      ]
    }
  }
}

Now, I’m perfectly capable of hand-editing my original code to a new format. I’ve done that roughly a zillion times in my career. I know how to do it. But that would’ve taken several minutes of drudgery (unless I wrote a macro or something to automate it, in which case it would’ve only taken a couple of hours). Copilot’s suggestion was exactly, to the letter, what I would have written manually, in a fraction of the time.

I have no interest in letting AI write code for me. I tell people that writing software is my favorite thing in the world, and they laugh, but I’m not joking. I wouldn’t let a computer take over my hobby any more than I’d let it play my piano for me, or feed my cat for me, or write my journal for me. I like doing those things. However, if it wants to take care of the mechanical grunt work like this while I concentrate on the more interesting bits, I’m happy to let it try.

If you want to really understand how Internet protocols work, I heartily recommend writing your own on top of UDP. You don’t have to work in the kernel. You can use just about any language you want. You can make it as simple or complex as you desire. Try it sometime! It’s instructive.

Python 3.13 launched today. I’ve done it. I’ve lived long enough to see a less-GIL’ed Python released to the public. Until now there’s been an unvirtuous cycle:

Python isn’t good at running CPU-intensive threaded code. → No one writes code like that. → There was no pressure to remove the GIL because no one writes code that would benefit from it. → Repeat.

I hope this is the first giant step toward good Python multithreading.

Google writes safer code with Rust

From “Google hails move to Rust for huge drop in memory vulnerabilities”:

In Google’s own shift towards using memory safe programming languages there has been a significant drop in the number of memory-related vulnerabilities, with memory safe vulnerabilities down to 24% in 2024 - a stark contrast from 2019 [76%] and well below the industry norm of 70%.

Memory safety is not the same as safety. You can still write bad logic in any language. It “just” gets rid of the majority of bugs so that programmers can concentrate on the more interesting parts.

Also, yes, of course you can write safe C code. No one with a large codebase ever has in practice, but it’s at least hypothetically possible. Wouldn’t rather not have to, though?

Sometimes Rust makes me so happy. I wrote this over the weekend:

let embedded_data = include_bytes!("../static/data.bin");
let my_set: HashSet<&[u8]> = embedded_data[7..].chunks(10).collect();

It does this:

  1. Read a binary file and embed it in the final executable as an array of bytes.
  2. Create a HashSet (Python folks: a set() of items of a specific type) where each element is an array of bytes.
  3. Skip the first 7 bytes of the binary file using Python-like slice notation.
  4. Create an iterator that emits 10-byte portions of the rest of the file, one at a time.
  5. Collect all the values from that iterator into… oh!, a HashSet<&[u8]> because Rust can tell what the type of the target variable is, so why make me repeat myself?

Rust isn’t magic. Other languages can do similar things if you poke at them enough. It’s more that 2 lines of builtin Rust can readably implement a reasonably sophisticated set of operations that get compiled into a static executable. That’s a very pleasant combination of features.

If you’re writing an SDK, don’t include a section on how to fetch all the pages of chunked results. That’s your job, not theirs. Make that the default interface and provide advanced methods to fetch a page at a time if your user specifically needs to for whatever reason.

Don’t make users write this:

all_results = []
results = sdk.get_items()
all_results.extend(results.items)
while results.has_more:
    results = sdk.get_more_items(results.next)
    all_results.extend(results.items)

Let them write this:

all_results = sdk.get_all_items()

Looking at you, AWS and Dropbox.

Language Server Protocol Launched a Golden Age of Editors

Microsoft developed Language Server Protocol (“LSP”) a few years ago to make it easier to add support for new languages to VS Code. Lots of smart people have written interesting things about LSP and I don’t want to rehash all that, but in summary: it gives people who like using a computer language a standard way to tell VS Code how to work with it.

Thing is, I don’t like VS Code at all. It’s a brilliant program, but under the covers it’s a web browser running a very clever JavaScript program. It doesn’t, and can’t, and won’t, ever feel like a native application, and that bothers me more than it should. I much prefer using what others call Mac-assed Mac apps. This is where LSP shows its real value.

Other apps can support LSP, too. Emacs users wrote a couple of different ways to connect those nifty new language servers to their favorite editor. Voila! Now Emacs has delightful support for every language that VS Code knows how to edit. So does Vim. And now, so do Nova and even the venerable BBEdit.

That last one blew me away. I’d seen it from a distance over the years. It’s impossible to use a Mac as a professional developer without at least being aware that it exists. BBEdit always struck me as a very neat, but very dated, niche editor that people kept using because they were too stubborn to switch. Oh, how wrong I was. I downloaded a copy a couple of weeks ago to kick the tires and found that since it can speak LSP, it might be the best programming environment I’ve ever used on my Mac. (“How’s its Python? Whoa! Is it that good with Rust? Whoa! How about… Terraform files? WHOA!”) 30 years of development as a text editor, plus all the effort that programming language users put into giving LSP broad and deep language support, yielded something that has incredible text mangling abilities and cutting-edge programming features. I love it. I’ve been trialing it as my main editor since then, and every day I appreciate it more.

I think we’re in a new golden age of programming editors. Now that any editor which can use LSP competes on a level playing field, the real competition is in subjective areas like the user interface, responsiveness, ergonomics, and extra functionality. Thanks to VS Code, those Mac-assed Mac apps redefine what developing software on a Mac can be like, and I couldn’t be more pleased with my options.