Lua 中 pairs() 的 "type signature" 是什么?
2018-6-7 18:46:34
收藏:0
阅读:84
评论:2
从 "Programming in Lua" 的章节 7.1 – Iterators and Closures 中可以看出,for foo in bar 循环需要 bar 的类型 (使用 Java 的类型来表示) 为 Supplier<Tuple>,而 for-in 会不断调用 bar 直到它返回 nil。
因此对于如下的代码:
for k,v in pairs( tables ) do
print( 'key: '..k..', value: '..v )
end
可以得出 pairs 的类型为 Function<Table,Supplier<Tuple>>。
我想要创建一个和 pairs 行为类似的函数,但是它会跳过第一个参数以 _ 开头的元组。
local function mypairs( list )
local --[[ Supplier<Tuple> ]] pairIterator = pairs( list )
return --[[ Supplier<Tuple> ]] function ()
while true do
local key, value = pairIterator()
if key == nil then
return nil
elseif key:sub(1,1) ~= '_' then
return key, value
end
end
end
end
但是这段代码无效,因为
--[[应该是:Supplier<Table>]] pairIterator = pairs({ c=3; b=2; a=1 })
当我调用它时,
pairIterator()
会返回
stdin:1: bad argument #1 to 'pairIterator' (table expected, got no value)
stack traceback:
[C]: in function 'pairIterator'
stdin:1: in main chunk
[C]: in ?
但是
pairIterator({ c=3; b=2; a=1 })
会返回
Lua>pairIterator({ c=3; b=2; a=1 })
c 3
点赞
用户369792
pairs() 返回三个独立的值:
- 一个参数为
(table, key)的函数,返回键和值 - 传入的表格
- 传递给函数的第一个“键”值(对于 pairs() 为 nil,ipairs() 为0)
因此像这样:
for k,v in pairs({a=1, b=13, c=169}) do print(k, v) end
可以这样完成:
local f,t,k = pairs({a=1, b=13, c=169})
local v
print('first k: '..tostring(k))
k,v = f(t, k)
while k ~= nil do
print('k: '..tostring(k)..', v: '..tostring(v))
k,v = f(t, k)
end
结果:
first k: nil
k: c, v: 169
k: b, v: 13
k: a, v: 1
你不必带上参数,这里有每个值的手动if语句:
function mypairs()
-- the function returned should take the table and an index, and
-- return the next value you expect AND the next index to pass to
-- get the value after. return nil and nil to end
local myfunc = function(t, val)
if val == 0 then return 1, 'first' end
if val == 1 then return 2, 'second' end
if val == 2 then return 3, 'third' end
return nil, nil
end
-- returns a function, the table, and the first value to pass
-- to the function
return myfunc, nil, 0
end
for i,v in mypairs() do
print('i: '..tostring(i)..', v: '..tostring(v))
end
-- output:
-- i: 1, v: first
-- i: 2, v: second
-- i: 3, v: third
对于你的 mypairs(list),只要键值有下划线,就可以继续调用从 pairs 返回的函数来获取下一个值:
local function mypairs( list )
local f,t,k = pairs(list)
return function(t,k)
local a,b = f(t, k)
while type(a) == 'string' and a:sub(1,1) == '_' do a,b = f(t,a) end
return a,b
end, t, k
end
local list = {a=5, _b=11, c = 13, _d=69}
for k,v in mypairs(list) do print(k, v) end
-- output:
-- c 13
-- a 5
你所链接的文档的迭代器只返回一个值,而 pairs() 返回 2 个,但你可以返回更多的值。for ... in ... 结构只有在第一个值非空时执行函数体。这里有一个版本,它还返回被跳过的键,但如果没有实际的值,则不会执行函数体,因此你可能看不到所有的 _ 键:
local function mypairs( list )
local f,t,k = pairs(list)
return function(t,k)
local skipped = {}
local a,b = f(t, k)
while type(a) == 'string' and a:sub(1,1) == '_' do
table.insert(skipped, a)
a,b = f(t,a)
end
return a,b,skipped
end, t, k
end
local list = {a=5, _b=11, c = 13, _d=69}
for k,v,skipped in mypairs(list) do
for i,s in ipairs(skipped) do
print('Skipped: '..s)
end
print(k, v)
end
2018-06-07 22:38:00
评论区的留言会收到邮件通知哦~
推荐文章
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?

您的基本问题是在 Lua 问题中使用 Java 逻辑。Java 和 Lua 是具有不同结构的不同语言,需要认识到这一点很重要。
pairs没有返回值;它有 多个 返回值。Java 完全缺乏这个概念。元组是一个可以存储和操作多个值的单一值。Lua 函数可以返回多个值。这在语法和语义上与返回包含多个值的表格是不同的。基于迭代器的
for语句将多个值作为输入,而不是一个多个值的表格或容器。具体而言,它存储三个值:一个迭代器函数,一个状态值(您用它来保存调用之间的状态),以及一个初始值。因此,如果您想模拟
pairs的行为,您需要能够存储和操作它的多个返回值。第一步是存储
pairs实际返回的内容:local f, s, var = pairs(list)您正在创建一个新的迭代器函数。因此,您需要返回它,但您还需要返回
pairs返回的s和var。您的返回语句应如下所示:return function(s, var) --[[具体内容在下面讨论]] end, s, var -- 返回 `pairs` 的返回值。现在,在您的函数内部,您需要用
s和var来调用f。这个函数将返回键值对。您需要正确处理它们:return function(s, var) repeat local key, value = f(s, var) if(type(key) ~= "string") then -- 非字符串类型无法包含下划线。 -- 而且不需要特殊处理 `nil`。 return key, value elseif(key:sub(1, 1) ~= '_') then return key, value end until true end, s, var -- 返回 `pairs` 的返回值。