最近,Lua 社区被一记重锤敲醒了。LuaJIT 的作者 Mike Pall 直接从上游 GitHub 仓库里删掉了部分旧版本的标签。这在开源圈里堪称“核选项”——通常会被视为不友好甚至粗鲁的举动。可熟悉内情的人却能理解他的可奈:太多项目死守着十多年前的 luajit-2.1.0-beta3 之类的标签不放,bug 报告还在源源不断地涌向早已修复的问题。
LuaRocks 的维护者 Hisham Muhammad 随即写了一篇短文《The Lua community needs to learn to move on》,把这背后更深的困境摊了开来。要理解他的愤怒,得先把一段近十五年的历史说清楚。
大约在 2011 年前后,官方 Lua(由巴西 PUC-Rio 大学维护,俗称 PUC Lua)发布了 5.2 版本。与此同时,Mike Pall 开发的高性能实现 LuaJIT 却选择停留在 5.1 的兼容层面。LuaJIT 以惊人的执行速度闻名,尤其在游戏、网络代理等高性能场景里几乎成为标配。可它的作者明确表示,不会跟进官方后续的语言改动。于是社区被迫分裂:一边是追求最新特性的官方 Lua,一边是死死抓住速度优势的 LuaJIT。
为了让同一份代码同时跑在官方解释器和 LuaJIT 上,库作者们找到了一个“最大公约数”——Lua 5.1。只要代码严格遵循 5.1 的语法和 API,它就能在两边都工作。这个策略在当时很聪明,却成了后来的枷锁。官方 Lua 继续向前走,陆续发布了 5.2、5.3、5.4,现在已经到了 5.5;每一次新版本都带来一些不兼容的改动。可因为 LuaJIT 始终锚定在 5.1,大量库作者不敢轻易丢掉 5.1 支持,生怕切断那些依赖 LuaJIT 的用户。结果就是,今天写一个新库,还得同时测试 5.1、5.2、5.3、5.4、5.5,再加上 LuaJIT 2.1、OpenResty 变体,甚至新兴的 3.0。维护成本被无限拉长。
Hisham 自己也承认,他曾经是这套兼容策略的推手之一。从早期的 compat-5.0 到后来的 compat-5.2、compat-5.3,他帮过不少人在新旧版本之间搭桥。可如今他的态度已经变了:如果 PUC-Rio 的 Roberto 和 Mike Pall 都已经对旧版本做了 EOL(结束生命周期),库作者们是不是也该学着放下?真正想用极老版本的人,就该连同那套老旧的生态一起用,而不是强迫整个社区永远背着二十年的历史包袱。
他甚至提出了自己的“小贡献”——Teal 语言。这门语言的目标类似 TypeScript 之于 JavaScript,不仅给 Lua 加上类型,还能一次写出代码,再分别生成面向 5.1 到 5.5 的目标。希望借此把大家从“必须死守 5.1”的锚点上松绑。
这篇文章在 Lobsters 上迅速引发了五十多条讨论。有人旗帜鲜明地支持:开源项目硬撑十年前的版本根本不现实,用户不该把“永久向后兼容”当成理所当然,维护者更不该把这种期待内化成义务。也有人泼冷水,指出 Lua 的特殊之处——它本质上是一门可嵌入语言,大量用户其实是通过游戏引擎、编辑器、模拟器等宿主程序接触到它的。Neovim 至今把 5.1 当作永久接口(很大程度上也是因为 LuaJIT),TIC-80 还在用 5.3,MAME 等项目依赖的 C++ 绑定也还没跟上最新版本。对库作者来说,丢掉旧版本支持,可能直接切断一大批真实用户。
更尖锐的批评则指向根因:PUC-Rio Lua 几乎每隔几年就在语言语义和 C API 上做出不兼容改动,每一次新的 5.x 发布都像一场迷你版的 Python 2 到 3 迁移。LuaJIT 的分裂只是放大了这个问题,真正拖累生态的,是上游不断制造的“小断裂”。有人直言,与其催促库作者放弃旧版本,不如先让 PUC-Rio 停止不必要的破坏性变更。
讨论里也出现了务实的声音。有人提到,免费软件本来就是礼物而非义务,维护者完全有权拒绝无尽的兼容请求;如果用户觉得某个老版本的修复至关重要,他们手里有源码,也有 AI 工具可以自己动手。另一些人则提醒,嵌入式场景和独立解释器场景本就不同,不能一刀切。
眼下,Lua 社区正站在一个熟悉却又尴尬的路口。一边是维护者日益沉重的负担,一边是真实世界里大量仍在运行的老代码和宿主环境。Hisham 的呼吁或许刺耳,却点出了一个很多语言社区最终都要面对的问题:什么时候该果断向前走,什么时候又该为那些无法轻易升级的人留下一条路。答案恐怕不会整齐划一,但至少,这场对话已经开始了。