Jul*_*ian 4 lambda lua scope variadic-functions
如果我想编写一个接受varargs的函数并返回一个接受vargas的函数,我会遇到模糊不清...的问题
function bind(func, ...) return function(...) func(..., ...) end end
Run Code Online (Sandbox Code Playgroud)
首先,你错过了关闭绑定功能的结束.
如果您有歧义,只需使用不同的名称解决它们.
function bind(func, ...)
return function(...) func(..., ...) end
end
Run Code Online (Sandbox Code Playgroud)
如果我们测试你的代码: bind(print, "a", "b", "c")(1,2,3)
你会得到输出:
1 1 2 3
如果在函数参数列表中有...或任何其他名称,则该变量将是该函数范围内的本地变量.它优先于优越范围内具有相同名称的任何其他变量.所以...在你的匿名函数中与函数绑定无关.
要解决此问题,您可以简单地执行类似的操作
function bind(func, ...)
local a = table.pack(...)
return function(...) func(table.unpack(a, 1, a.n), ...) end
end
Run Code Online (Sandbox Code Playgroud)
现在调用bind(print,"a","b","c")(1,2,3)将输出:
1 1 3 3
要了解b和c发生了什么,请阅读本节:https://www.lua.org/manual/5.3/manual.html#3.4.11
(当然还有Lua手册的其余部分)
调用函数时,参数列表将调整为参数列表的长度,除非该函数是vararg函数,该参数由参数列表末尾的三个点('...')表示.vararg函数不会调整其参数列表; 相反,它收集所有额外的参数并通过vararg表达式将它们提供给函数,该表达式也写为三个点.此表达式的值是所有实际额外参数的列表,类似于具有多个结果的函数.如果在另一个表达式内或表达式列表的中间使用vararg表达式,则将其返回列表调整为一个元素.如果表达式用作表达式列表的最后一个元素,则不进行任何调整(除非最后一个表达式括在括号中).
所以像func(...,...)这样的东西永远不会起作用,即使......是两个不同的列表.
为避免这种情况,您必须连接两个参数列表.
function bind(func, ...)
local args1 = table.pack(...)
return function(...)
local args2 = table.pack(...)
for i = 1, args2.n do
args1[args1.n+i] = args2[i]
end
args1.n = args1.n + args2.n
func(table.unpack(args1, 1, args1.n))
end
end
Run Code Online (Sandbox Code Playgroud)
bind(print,"a",nil,"c")(1,nil,3)
这最终给了我们想要的输出:
没有1无1
但我相信你可以想出一个更好的方法来实现你的目标,而不是连接各种varargs.