11 | 剖析Lua唯一的数据结构table和metatable特性
温铭
该思维导图由 AI 生成,仅供参考
你好,我是温铭。今天我们一起学习下 LuaJIT 中唯一的数据结构:table。
和其他具有丰富数据结构的脚本语言不同,LuaJIT 中只有 table 这一个数据结构,并没有区分开数组、哈希、集合等概念,而是揉在了一起。让我们先温习下之前提到过的一个例子:
这个例子中, color 这个 table 包含了数组和哈希,并且可以互不干扰地进行访问。比如,你可以用 ipairs 函数,只遍历数组部分的内容:
table 的操作是如此重要,以至于 LuaJIT 对标准 Lua 5.1 的 table 库做了扩展,而 OpenResty 又对 LuaJIT 的 table 库做了更进一步的扩展。下面,我们就一起来分别看下这些库函数。
table 库函数
先来看标准 table 库函数。Lua 5.1 中自带的 table 库函数并不多,我们可以大概浏览一遍。
table.getn 获取元素个数
我们在 标准 Lua 和 LuaJIT 章节中曾经提到过,想正确地获取到 table 所有元素的个数,在 LuaJIT 中是一个老大难问题。
对于序列,你用table.getn 或者一元操作符 # ,就可以正确返回元素的个数。比如下面这个例子,就会返回我们预期中的 3。
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
- 深入了解
- 翻译
- 解释
- 总结
LuaJIT中的`table`是唯一的数据结构,融合了数组和哈希的特性,没有区分开数组、哈希、集合等概念。文章介绍了LuaJIT中`table`的操作和扩展函数,包括标准table库函数和LuaJIT扩展的函数。其中,`table.new`用于新建table并预先分配数组和哈希的空间大小,而`table.clear`用于清空table里的所有数据。此外,文章还介绍了元表的概念和作用,以及如何使用元表来实现面向对象编程。通过元表,可以重载操作符、定义转换为字符串的函数,以及模拟类和类方法。这些内容对于读者快速了解LuaJIT中table和metatable的特性具有很好的指导意义。文章内容深入浅出,涵盖了LuaJIT中table和metatable的基本概念和高级应用,对于读者理解和应用LuaJIT具有很好的参考价值。
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《OpenResty 从入门到实战》,新⼈⾸单¥59
《OpenResty 从入门到实战》,新⼈⾸单¥59
立即购买
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
登录 后留言
全部留言(18)
- 最新
- 精选
- 奕直接 lua 运行 table.getn 会报这样的错的 lua: table.lua:7: attempt to call a nil value (field 'getn') 我查了一下, lua5.1 之后把这方法去掉了,那么为什么 luajit 和 openresty 不把这个方法废弃呢?还保留呢?
作者回复: 因为 LuaJIT 是基于 Lua 5.1的语法来实现的,并没有跟随Lua 5.2 和 5.3
2019-06-194 - 小飞哥 超級會員localhost: ~/geektime/lua $ resty -e 'local color = {first = "red", "blue", third = "green", "yellow"} > color.first = nil > for k, v in pairs(color) do > print(v) > end' blue yellow green localhost: ~/geektime/lua $ resty -e 'local color = {first = "red", "blue", third = "green", "yellow"} > table.remove(color, 1) > for k, v in pairs(color) do > print(v) > end' yellow green red 看结果为什么打印一个是正序,一个是倒序呢?
作者回复: 字典的顺序是不保证的,大部分语言都是如何
2019-06-222 - John老师,能否专门讲解一下lua面向对象是如何实现继承,抽象类的,我看了orange的源码发现不太容易理解,源码如下: -- local BasePlugin = Object:extend() function Object:extend() local cls = {} for k, v in pairs(self) do if k:find("__") == 1 then cls[k] = v end end cls.__index = cls cls.super = self setmetatable(cls, self) return cls end function Object:implement(...) for _, cls in pairs({...}) do for k, v in pairs(cls) do if self[k] == nil and type(v) == "function" then self[k] = v end end end end
作者回复: 不推荐用 Lua 的 table 来模拟实现继承等这种复杂的功能,就像你说的一样,可读性太差,一般人的脑子都转不过来。。。
2019-06-2031 - helloworld函数不可貌相,海水不可(斗量) :)
作者回复: :)感谢 fix typo
2019-06-191 - 奕在luajit 扩展的table 函数中 local new_tab = require('table.new') 或者 require('table.clear') 用 luajit 去执行 都会报错找不动 moudule的错误的 luajit: table_luajit.lua:1: module 'table.new' not found: luajit 的版本 2.0.5
作者回复: 需要 LuaJIT 2.1 的版本才行, 文档在这里:https://github.com/LuaJIT/LuaJIT/blob/v2.1/doc/extensions.html#L218
2019-06-1921 - 英雄是重载还是重写?java里面的重载是:指同一个类中的多个方法具有相同的名字,但这些方法具有不同的参数列表,即参数的数量或参数类型不能完全相同 方法重写是:存在子父类之间的,子类定义的方法与父类中的方法具有相同的方法名字,相同的参数表和相同的返回类型
作者回复: 按照你的定义就是重写。Lua 没有类的概念,是模拟出来的,所以做不到重载这么高级。
2019-07-11 - ArtEngr“另外,超出预设的空间大小,也可以正常使用,只不过性能会退化” 很多时候与外界交互数据,无法准确知道table大小。
作者回复: 可以设置大一些,留一些缓存
2019-06-21 - wusirationlua-resty-mysql 模拟OO,个人理解是便于复用mysql连接,无需反复开启mysql连接;麻烦老师解惑一下2019-07-019
- 石头Rockysetmetatable({ sock = sock }, mt) 构造函数返回的table是{ sock = sock }这个表。 当调用方使用 set_timeout方法时,在表内找不到set_timeout方法,便会去__index所指的_M中去寻找。2019-06-197
- Triple Z 💤`table.nkeys` 和 `table.getn` / `#` 有什么样的性能差异吗?我查了下 NYI 列表,貌似 `getn` 一样可以被 JIT。从实现上来看,貌似 `nkeys` 也是 O(n)。2022-12-16归属地:广东1
收起评论