hisham hm

🔗 The Lua community needs to learn to move on

This could be a long blog post, but I’ll try to make it a short one, basically expanding on a GitHub comment I just posted.

Recently, Mike Pall deleted some tags for old LuaJIT versions from his upstream GitHub repo. That is a pretty nuclear option for forcing people to upgrade, and in normal circumstances it would be seen as a very, err, unfriendly move in any FOSS situation.

But I can see the frustration he’s probably coming from. I know there are tons of projects out there stuck in tags like `luajit-2.1.0-beta3` for ages. He’s most likely getting bug reports for bugs fixed over ten years ago. I know because it’s the same in the LuaRocks world, where we keep getting bug reports for LuaRocks 2.0.8 from 2012 because distros haven’t updated them. I’ve also been on the other side and I know how taxing it is for distro maintainers, so I’m not pointing fingers. I’m just saying that maintenance and getting people to update is hard.

This is, however, an especially difficult problem in the Lua community.

Ever since the Lua/LuaJIT split around 5.2 (gosh, that was… 15 years ago!?), the community has gotten in this paralyzing tendency of supporting old versions forever, even when upstream doesn’t support them anymore. People making Lua libraries keep testing their packages against Lua 5.1, 5.2, 5.3, 5.4 and now 5.5; then LuaJIT 2.1, sometimes the OpenResty variant as well, and now 3.0.

I understand that Lua is an embeddable language and if you make a decision in a point in time to bundle, say Lua 5.2 in your app and you build a plugin ecosystem around it, then you’re married to it forever. But then that’s your app’s ecosystem to take care.

For Lua as an extensible language (that is, an interpreter + libraries), the story should be different, and it should be more like any other dynamic/scripting language out there. We should really be (gradually?) moving into supporting only the latest PUC-Rio Lua and the latest LuaJIT, at best.

I know why we ended up where we are. I know the history because I was there: with the Lua/LuaJIT schism, people wanted to support both environments, and targeting 5.1 was a good way to support both. And then 5.2, 5.3, etc. came along and people wanted to keep supporting the latest PUC-Rio Lua, but still felt tied to the 5.1 anchor. I’m sure I’m partly to blame for this because I engaged in this and helped others, by maintaining compat-5.3, itself an evolution of compat-5.2, with a history tracing all the way back to compat-5.0, which predates my involvement with Lua… and then we’re talking over 20 years ago.

My small contribution to try to undo this, nowadays, is Teal, a language that aims to be to Lua what TypeScript is to JavaScript: it not only aims to bring types to the language, but it also aims to bridge the version gaps. You can write Teal once, and then generate Lua with –gen-target=5.1 all the way to –gen-target=5.5. Hopefully this will help untie writers of Lua code from the Lua 5.1 anchor.

But even if you’re not using Teal, and you’re a Lua library author, consider doing what Roberto and Mike are doing: they do EOL their language versions. LuaJIT 1.0 is EOL, LuaJIT 2.0.0 is EOL (there’s a 2.0 bugfix branch, but the old tarballs are EOL), and all PUC-Rio Lua versions up to 5.3 are EOL (”There will be no further releases of Lua 5.3.” — note that as of August 2026, this is not said of Lua 5.4; there’s usually one last release a while after the next major Lua 5.x comes out).

If Roberto and Mike are EOLing the interpreters, maybe we should be doing the same for the libraries. If people really want to be using very very old versions of Lua, they should be using very very old versions of the supporting ecosystem as well, and not forcing maintainers into supporting 20+ years of legacy at all times.

🔗 Sorting “git branch” with most recent branches last

This is something I always have to look up whenever I set up a new machine, so I might as well store it here:

git config branch.sort committerdate --global

I never felt the need to have “dotfiles” repo because the GoboLinux EnhancedSkel was effectively my dotfiles repo! Maybe I need to consider one now!

🔗 Frustrating Software

There’s software that Just Works, and then there’s Frustrating Software.

htop Just Works. LuaRocks is Frustrating Software. I wrote them both.

As a user and an author of Frustrating Software, there’s a very particular brand of frustration caused by its awkward workflows.

I recognize it as a user myself when using software by others, and unfortunately I recognize it in my users when they fail to use my software. I know the answer in both cases is “well, the workflow is awkward because reasons”. There’s always reasons, they’re always complicated.

I wonder if I would know that were I not a developer myself.

Well-intentioned awkward free software still beats slick ill-intentioned proprietary software any day of the week. Both cause frustration, but the nature of the frustration is so, so different. The latter pretends it Just Works, and the frustration is injected for nefarious reasons. The frustration in the former is an accidental emergent behavior. I feel empathy to that, but it’s no less frustrating.

I wonder if non-developer end-users feel the difference, or if the end result is just the same: “this doesn’t work”. I’ve seen people not realizing they were being manipulated by slick ill-intentioned software. I’ve seen people dismissing awkward well-intentioned software outright with “this is broken”.

If users were looking at a person performing a task in front of them (say, an office clerk) rather than a piece of code, everyone would be able to tell the difference instantly.

In the end, all we can do as authors of well-intentioned free software is to be aware when we ended up building Frustrating Software.

Don’t be mad at users when they don’t “get it” that it’s “because reasons”.

Don’t embrace the awkwardness retroactively as a design decision; just because it can explained and “that’s how it is” it doesn’t mean that “that’s how it should be” (and definitely don’t turn it into a “badge of honor” to tell apart the “initiated”).

Once we step back after the defensive kneejerk reaction when our work is criticized, it is not that hard to tell apart someone just trolling from genuine frustration from someone who really tried and failed to use our software. Instead of trying to explain their frustration away to those people, take that as valuable design feedback into trying to improve your project into something that Just Works.

As for me? LuaRocks has a long way to go (because reasons!), but we’ll get there.

🔗 What every programmer should know about what every programmer should know

I won’t deny it. I came up with the title for this post before coming up with the actual content. It came to my head and it was just too good to pass, because it entices you to think about that subject. What does every programmer need to know, after all?

If you run into any other of those lists, let me know at h@ this website’s domain!

🔗 There are two very different things called “package managers”

Earlier today, Ludovic Courtès asked these questions on Mastodon:

Are npm/crates.io just a different approach to distributing software, compared to Linux distros?

Or is there something more fundamental about their approach, how it affects user/developer relations, and how if affects user autonomy?

My take on these questions is that to me there are two fundamental differences:

1) npm/crates.io/LuaRocks (language package managers) are package managers for programmers. They ship primarily modules/libraries; apt/rpm/etc (system package managers) are package managers for end-users. I don’t expect a non-programmer to ever use cargo but I expect a Ubuntu user to use apt (even if via a GUI).

2) language package managers cut the “middleman” and allow module/library devs to make them available to other devs right away, without someone like a Debian developer having to deem them relevant/ready enough for packaging.

The fact that there is no curation is a feature for language package managers, just like the fact that there is curation is a feature for system package managers.

The reason why system package managers are curated is for end-user protection. The reason why language package managers are not curated is to provide developer autonomy. There is a wide gradient between these two things.

If as a developer you put too many hurdles between me and the library I want to use in the name of “protecting” me, I’m gonna skip your package manager and just fetch my dependencies from the upstream source.

For end-users just trying to keep their browser up-to-date, I understand the story is completely different.

There are other practical reasons why developers use language-specific package managers, of course. One of them is dealing with dependency versioning. By having per-project trees (think of node_modules in npm), each project can define their own dependency versions, regardless of what is available system-wide (if it is available at all). This is something that happens in practice, but that is not necessarily a fundamental design difference between language and system manager. In our 2019 paper we discussed alternatives, but the approaches we suggested there are not the general state of the world today.

An aside: when talking about projects adopting or not certain package managers, one needs to keep an eye for the motivations. I’ve seen questionable arguments from companies keeping packages away from community repos (for example, to retain control over download metrics). But in my experience, I’ve only ever seen this happening to system package managers, but never to language package managers, which just seem to reiterate how different these two universes are.

In an ideal world, system package managers and language package managers would be able to cross-reference each other to avoid the duplication of packaging work we see everywhere. This is something we talked about in the paper linked above. In fact, I’ve been trying to preach the gospel of cross-language links across ecosystems since at least… *checks git, or rather, cvs history*2003.

I’m as sympathetic to the ideal as they come, but the reality is that we need to deal with these two universes for now (…for a significant definition of “now”).

Amidst the lively debate in Mastodon, my friend Julio brought up the elephant in the room:

(puts Diogenes beard):
“Docker.”

…to which I can only nod my head in agreement and say: the success of Docker is the developer world’s tacit acknowledgement that package management has failed.

(For anyone else reading this tongue-in-cheek comment without further context: I have authored two package managers, both in the language side and distro side of the game. If that remark feels excessive, just s/has failed/is hard/, but my point still stands.)

Don’t get me wrong, package management has evolved greatly over the years, but as a community we’re still understanding it. There are two very different things that are both called package managers, and they serve different purposes. Another world is possible, but it will take a lot of gradual change, and “if only everyone would adopt my package manager where everything works” is not a solution (that applies to people living inside the bubble of their own language ecosystem as well!). Age has turned me from a revolutionary into a reformist.


Follow

🐘 MastodonRSS (English), RSS (português), RSS (todos / all)


Last 10 entries


Search


Admin