最近在搞迁移,准备将项目依赖的 Lua 5.3 迁移到 5.4 上面去,先翻译一下手册的第八章,强迫自己读完, 原文地址

这里我们列出了从 Lua 5.3 迁移到 Lua 5.4 可能会遇到的兼容性问题

你可以通过设置参数重新编译 Lua(详情参考 luaconf.h),来避免其中的一些兼容性问题。但是,所有兼容选项都会在未来被移除掉。当这些选项被移除时,兼容性问题就会暴露出来。所以,当你有机会的时候,你应该尝试用没打开任何兼容选项的 Lua,来测试你的代码。这样会让迁移到新版本 Lua 的过程变得更容易

Lua 版本间有可能发生 C API 的变更,前提是这些变更不会引起程序源码的改变,比如数值常量或者将函数以宏实现。因此,你永远不应该假设不同 Lua 版本间,二进制是兼容的。使用新版本时谨记重新编译使用 Lua API 的客户端

与之类似的还有预编译代码块,Lua 版本间可以改变预编译代码块的内部表示方式;预编译代码块在不同 Lua 版本间不兼容

官方发布的标准路径,在不同版本间也有可能改变

8.1 语言上的不兼容性

  • 字符串到数字的强转,在算术运算和位运算中被移除出核心语言了。string 库通过字符串元方法,为算术运算提供了类似的操作(但不支持位运算)然而,与之前版本不同,新的实现保留了字符串中隐含的数字类型。比方说,”1” + “2” 的结果现在是整型而非浮点了
  • 溢出的文本化的十进制整数常量,现在会按浮点处理,而不是回绕。如果你需要回绕,可以使用 16 进制来表示这些常量(这样就会将他们用做整型)
  • 移除了使用 __lt 元方法来模拟 __le 的行为。需要 __le 时,必须显式声明 __le 方法
  • 整数 for 循环的语义有细节上的改动,控制变量永远不会回绕了
  • goto 语句的标签不能在同一可见域内定义两次,即使其中一个标签是在一个封闭语句块内
  • 当回收一个对象的时候,Lua 不会忽略不是函数的 __gc 元方法。只要存在 __gc,无论 __gc 是何值均会被调用(不能调用的值会产生一个警告信息,正如调用析构函数时产生的其他错误一样)

8.2 库的不兼容性

  • print 函数不再调用 tostring 方法来格式化参数了;而是硬编码了这个功能。你应该用 __tostring 来定义如何格式化这个值
  • math.random 使用的伪随机数生成器,现在改用了一定程度上随机的种子,也使用了另一个随机算法
  • utf8 库的解码函数默认代理值(surrogate)为非法代码数。这些函数有一个额外参数,可以让其变得对代理值更宽容
  • collectgarbage 的 setpause 和 setstepmul 选项被废弃了。你需要用新的 incremental 选项来设置它们
  • io.lines 函数现在返回 4 个值而不是 1 个值了。当 io.lines 用于其他单参数函数时就会出错,比如 load(io.lines(filename, “L”))。可以将调用藏进括号里来调整返回值的数量

8.3 API 的不兼容性

  • 完整的 userdata 现在可以有任意数量的 user value 了。因此,lua_newuserdata, lua_setuservalue, lua_getuservalue 将被 lua_newuserdatauv, lua_setiuservalue 和 lua_getiuservalue 取代,他们有一个额外的参数。出于兼容性的目的,老的名字可以宏的形式继续工作,默认只处理一个 user value。注意,新的 API 下不含 user value 的 userdata 会更节省内存
  • lua_resume 有一个额外参数。这个参数返回协程压栈了多少个值。(在之前的版本里,这里是栈上所有的值)
  • lua_version函数现在直接返回一个版本数字,而不是版本数字的地址了。带有静态链接Lua核心副本的库应该能和Lua核心正常工作,没有必要确认他们是在同一个地址空间
  • LUA_ERRGCMM常量被移除。析构器里的错误永远不会被传播;他们只会产生一个警告信息
  • lua_gc函数的LUA_GCSETPAUSE和LUA_GCSETSTEPMUL选项被废弃了。你应该使用新的LUA_GCINC来设置他们