Lua中table.insert直接传表达式作第二个参数报错,存变量则正常
Lua中table.insert传入gsub表达式报错的原因与解决办法
问题现象
在Lua REPL中执行以下代码时会出现矛盾的结果:
❯ lua Lua 5.4.6 Copyright (C) 1994-2023 Lua.org, PUC-Rio > tab={}; str='a'; z=str:gsub('a', 'b'); table.insert(tab, z); print(tab[1]) b > tab={}; str='a'; table.insert(tab, str:gsub('a', 'b')); print(tab[1]) stdin:1: 'insert'的第2个参数无效(预期为数字,实际传入字符串) 栈回溯: [C]: in function 'table.insert' stdin:1: in main chunk [C]: in ?
直接将str:gsub('a', 'b')作为table.insert的第二个参数传入会触发类型错误,但先把该表达式的结果存入变量再传入就可以正常执行。
核心原因
问题出在Lua的多返回值机制上:string.gsub(包括用冒号语法调用的str:gsub)会返回两个值——第一个是替换后的字符串,第二个是成功完成替换的次数。
当你直接把str:gsub('a', 'b')作为参数传给table.insert时,Lua会把这两个返回值全部传递给函数。此时table.insert收到的三个参数分别是:tab、替换后的字符串"b"、替换次数1。而table.insert的参数逻辑是:
- 传2个参数时:
table.insert(表, 值),作用是在数组末尾追加这个值 - 传3个参数时:
table.insert(表, 位置, 值),要求第二个参数必须是数字类型的位置索引
这时候第二个参数被当成了插入位置,但它是字符串类型,自然就触发了“预期为数字,实际传入字符串”的错误。
而把表达式结果存入变量z时,Lua在给单个变量赋值时只会取多返回值的第一个,所以z的值就是替换后的字符串"b",传给table.insert时只有两个参数,符合追加值的逻辑,因此可以正常执行。
解决办法
有两种简单的解决方式:
- 方式一:先将表达式结果赋值给变量,再传入
table.insert(即已经验证有效的写法)tab = {}; str = 'a'; z = str:gsub('a', 'b'); table.insert(tab, z); print(tab[1]) - 方式二:用括号包裹表达式,强制只取第一个返回值
括号会让Lua把多返回值表达式转换为单个值(仅保留第一个返回值),这样传给tab = {}; str = 'a'; table.insert(tab, (str:gsub('a', 'b'))); print(tab[1])table.insert的就只有替换后的字符串,不会触发三参数的重载逻辑。
内容的提问来源于stack exchange,提问作者Steven Lu
相关产品推荐
相关产品推荐

