7

1つの引数を持つlua関数が与えられた場合、この引数を固定値にバインドして、引数のない関数を取得することは可能ですか?

より一般的には、lua関数の特定の入力引数を特定の値にバインドするにはどうすればよいですか?

4

2 に答える 2

12

はい、これはファーストクラスの値として機能するほとんどすべての言語で実行できます。

function f1(a)
   return a+1
end

function bind(a)
   return function() return f1(a) end
end

local f2 = bind(42)
print(f2())
-- 43

この特定の例は、特定の関数と引数の数で機能しますが、代わりに任意の関数/引数を取るように簡単に拡張できます。

于 2012-06-20T11:42:16.247 に答える
1

Boost :: bindが行うことを行うためのヘルパー関数を作成しました:

  • プレースホルダーを処理して、任意の位置引数を置き換えることができます
  • それはどこでもnilを処理します

使用法 :

function_binder(base_function, placeholders_format, args...)

  • base_function(function):ラップする関数
  • placeholders_format(文字列):引数の配置方法を表し、各文字は引数を表します
    • .:ラッパーからの引数を表す
    • 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

function_binderコードは次のとおりです。

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

于 2016-09-01T14:30:15.053 に答える