I just made a helper function to do what Boost :: bind does:
- It processes the placeholder to be able to replace any positional argument
- It handles nothing anywhere
Using:
function_binder(base_function, placeholders_format, args...)
- base_function (function): function to carry
- placeholders_format (string): represent how arguments should be placed, each character represents an argument
.
: present an argument from the shellA
: represents an argument from a binder~
: represent all pending arguments from the shell
See the following example for a better understanding.
A simple example:
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
You can also use the built-in function:
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
You can also create complex things:
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
Object oriented path
Customization
To make more OO files, you can use the debug library:
-- apply metatable to all function debug.setmetatable(function()end, { __index = { bind = function_binder, }, })
Using
local debug_print = print:bind("A~", "DEBUG:") debug_print("add some log") -- => prints: DEBUG: add some log
Here is the function_binder code:
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
It works great with Lua 5.3
Hosting here: https://github.com/Bew78LesellB/luaMiscTests/commit/e9e52aea7933b58332fff36738356f18aed3db92