如何为 Lua 实现 bind() 函数?
2013-8-14 14:31:55
收藏:0
阅读:88
评论:4
我想为 Lua 实现 bind(),在 Javascript 中广泛用于创建闭包。
以下代码演示了一个参数的情况:
function bind(func, arg1)
return function (...)
return func(arg1, ...)
end
end
local x = { data = 1 }
function x.print(self)
print self.data
end
outputX = bind(x.print, x)
outputX() -- print 1
我的问题是:如何支持任意数量的绑定参数?
点赞
用户734069
因为 Lua 处理 ... 和多个返回值的方式,显而易见的方法无法正常工作:
function bind(func, ...)
local args = {...}
return function (...)
return func(unpack(args), ...)
end
end
这样做是行不通的,因为unpack函数返回的多个值将会被 调整为一个返回值,这是表达式中使用方式导致的。
你可以这样做,它将在一定程度上起作用:
function bind(func, ...)
local nargs = select("#", ...)
local args = {...}
return function (...)
local newArgs = {...}
local fullArgs = {}
copy(fullArgs, args)
copy(fullArgs, {...})
return func(unpack(fullArgs))
end
end
上面的 copy 函数只是一个简单的重复利用元素从一个表复制到另一个表的公用函数。
在这里的限制是不能有任何参数在 bind 调用或函数对象中是 nil。如果有的话,那么这些参数及其后面的参数都将被删除。
使用 C API 可以很容易地做到准确,但由于 Lua 语言的限制,这种方法需要正确地处理 nil 相当困难。
2013-08-14 10:49:49
用户2458544
定义一个 unpackN 函数来解开一个参数表:
function unpackN(argss, i)
i = i or 1
local iLocal = i
for _, args in ipairs(argss) do
local argsN = #args
if iLocal <= argsN then
return args[iLocal], unpackN(argss, i+1)
end
iLocal = iLocal-argsN
end
end
然后像下面这样使用它:
function bind(func, ...)
local A = {...}
return function (...)
local B = {...}
return func(unpackN {A, B} )
end
end
2013-08-14 13:25:24
用户783743
尝试一下:
function bind(func, ...)
local rest = {...}
return function (...)
local args = {}
for i = 1, #rest do
args[i] = rest[i]
end
for i = 1, select("#", ...) do
table.insert(args, select(i, ...))
end
return func(unpack(args))
end
end
现在你拥有了一个可变参数的绑定函数:
function add(...)
local sum = 0
for i = 1, select("#", ...) do
sum = sum + select(i, ...)
end
return sum
end
local add_2_3 = bind(add, 2, 3)
print(add_2_3(5))
希望这有所帮助。
2013-08-14 14:10:40
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的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 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
使用 lua-vararg 可以编写:
local va = require "vararg" function bind(f, ...) local outer_args = va(...) local function closure (...) return f(va.concat(outer_args, va(...))); end return closure; end bind(print, 1, 2, 3)(4,5,6)这是纯 Lua 实现的:
function packn(...) return {n = select('#', ...), ...} end function unpackn(t) return (table.unpack or unpack)(t, 1, t.n) end function mergen(...) local res = {n=0} for i = 1, select('#', ...) do local t = select(i, ...) for j = 1, t.n do res.n = res.n + 1 res[res.n] = t[j] end end return res end function bind(func, ...) local args = packn(...) return function (...) return func(unpackn(mergen(args, packn(...)))) end end bind(print, 1, nil, 2, nil)(3, nil, 4, nil)