1つの引数を持つlua関数が与えられた場合、この引数を固定値にバインドして、引数のない関数を取得することは可能ですか?
より一般的には、lua関数の特定の入力引数を特定の値にバインドするにはどうすればよいですか?
1つの引数を持つ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
この特定の例は、特定の関数と引数の数で機能しますが、代わりに任意の関数/引数を取るように簡単に拡張できます。
Boost :: bindが行うことを行うためのヘルパー関数を作成しました:
function_binder(base_function, placeholders_format, args...)
.
:ラッパーからの引数を表すA
:バインダーからの引数を表す~
:ラッパーからの保留中のすべての引数を表す理解を深めるには、次の例を参照してください。
local function divide(a, b)
return a / b
end
local div_by_4 = function_binder(divide, ".A", 4)
print(div_by_4(12)) -- => prints: 3
local div_12_by = function_binder(divide, "A.", 12)
print(div_12_by(4)) -- => prints: 3
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
より多くのOOを実行するには、デバッグライブラリを使用できます。
-- 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
Lua5.3で完全に動作します
ここでホスト:https ://github.com/Bew78LesellB/luaMiscTests/commit/e9e52aea7933b58332fff36738356f18aed3db92