可以在Lua中模拟bind吗?
给定一个带有一个参数的lua函数,是否可以将该参数绑定到一个固定值以获得一个没有参数的函数可以在Lua中模拟bind吗?,lua,Lua,给定一个带有一个参数的lua函数,是否可以将该参数绑定到一个固定值以获得一个没有参数的函数 更一般地说,如何将lua函数的某些输入参数绑定到某些值 是的,这几乎可以用任何具有函数作为一级值的语言来实现 function f1(a) return a+1 end function bind(a) return function() return f1(a) end end local f2 = bind(42) print(f2()) -- 43 这个特定的示例适用于特定的函数和
更一般地说,如何将lua函数的某些输入参数绑定到某些值 是的,这几乎可以用任何具有函数作为一级值的语言来实现
function f1(a)
return a+1
end
function bind(a)
return function() return f1(a) end
end
local f2 = bind(42)
print(f2())
-- 43
这个特定的示例适用于特定的函数和参数数量,但是可以很容易地扩展为使用任意函数/参数。我刚刚创建了一个帮助函数来实现Boost::bind的功能:
- 它处理占位符,以便能够替换任何位置参数
- 它在任何地方都能处理零
function\u活页夹(基本函数、占位符格式、参数…)
- base_函数(function):要包装的函数
- 占位符\ U格式(字符串):表示参数的放置方式,每个字符表示一个参数
:表示包装器中的参数
:表示活页夹中的参数A
:表示包装器中所有挂起的参数~
-- apply metatable to all function
debug.setmetatable(function()end, {
__index = {
bind = function_binder,
},
})
用法
以下是功能代码:
它与Lua5.3完美配合
托管在此处:您的意思是currying(返回函数的函数)?当然可以,只需从函数返回一个函数即可。请参阅。它与咖喱不同,因为它不需要对函数本身进行任何更改。Boost的绑定是我想要实现的一个很好的例子:@benno:那么Boost.bind在哪些方面不需要更改函数呢?它创建一个新的函数对象,将给定的参数转换为对旧的可调用对象的调用。这将有效地更改函数。类似函数bind(f,…)local args={…}返回函数(…)返回f(unpack(args),…)end。这将绑定任意数量的参数,并允许添加额外的参数。类似函数add(a,b)返回a+b end;add5=绑定(add,5);print(add5(6))@jpjacobs-
f(unpack(args),…)
仅使用数组的第一个元素args
。我们需要构建一个新数组,作为两个数组args
和{…}
的串联,然后才能解包它。
local debug_print = function_binder(print, "A~", "DEBUG:")
debug_print("some logs for debug")
-- => prints: DEBUG some logs for debug
-- '~' will put all following arguments:
debug_print("some", "logs", "for", "debug")
-- => prints: DEBUG some logs for debug
local function stuff(...)
print("Args: ", ...)
end
local wrapper = function_binder(stuff, ".A..AA~", "two", "five", "six")
wrapper(1, 3, 4, 7, nil, 9)
-- => prints: 1 two 3 4 five six 7 nil 9
-- apply metatable to all function
debug.setmetatable(function()end, {
__index = {
bind = function_binder,
},
})
local debug_print = print:bind("A~", "DEBUG:")
debug_print("add some log")
-- => prints: DEBUG: add some log
local function packed_args_append(packed, nb_insert, ...)
nb_insert = nb_insert > 0 and nb_insert or select('#', ...)
for i = 1, nb_insert do
packed[packed.n + 1] = select(i, ...)
packed.n = packed.n + 1
end
end
-- replace table.unpack as it doesn't always handle nil values correctly..
local function unpacknil(packed)
local nb_args = packed.n
local function unpack_n(n)
if n == nb_args then
return packed[n]
end
return packed[n], unpack_n(n + 1)
end
return unpack_n(1)
end
function function_binder(self, placeholder_format, ...)
local placeholders = table.pack(...)
return function(...)
local args = {n = 0}
local arg_idx = 1
local placeholder_idx = 1
for c in placeholder_format:gmatch"." do
if c == 'A' then
packed_args_append(args, 1, placeholders[placeholder_idx])
placeholder_idx = placeholder_idx + 1
elseif c == '.' then
packed_args_append(args, 1, select(arg_idx, ...))
arg_idx = arg_idx + 1
elseif c == '~' then
packed_args_append(args, -1, select(arg_idx, ...))
break
end
end
--return self(table.unpack(args))
return self(unpacknil(args))
end
end