lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Hi all,

This demonstrates how to implement boost::bind while still producing
an efficient binding. The key is code generation. So e.g. bbind
(print,_2,_1,true) will generate the following code string:

return function (fn,_v1)
	return function(_1,_2) return fn(_2,_1,_v1) end
end

Which is then compiled and called twice, first to compile the wrapper
function and next to extract the wrapped function.

This is of course a relatively expensive function, but the resulting
binding is fast.

steve  d.


-- testbind.lua
-- Lua implementation of boost::bind
-- http://www.boost.org/doc/libs/1_38_0/libs/bind/bind.html
local append = table.insert
local concat = table.concat

_1,_2,_3,_4,_5 = {'_1'},{'_2'},{'_3'},{'_4'},{'_5'}
local placeholders = {[_1]=true,[_2]=true,[_3]=true,[_4]=true,[_5]=true}

function bbind(fn,...)
	local args = {...}
	local holders,parms,bvalues,values = {},{},{'fn'},{}
	local np,nv = 1,1
	for i,a in ipairs(args) do
		if placeholders[a] then
			append(holders,a[1])
			append(parms,'_'..np)
			np = np + 1
		else
			local v = '_v'..nv
			append(bvalues,v)
			append(holders,v)
			append(values,a)
			nv = nv + 1
		end
	end
	bvalues = concat(bvalues,',')
	parms = concat(parms,',')
	holders = concat(holders,',')
	local fstr = ([[
return function (%s)
	return function(%s) return fn(%s) end
end
]]):format(bvalues,parms,holders)
	local res,err = loadstring(fstr)
	res = res()
	return res(fn,unpack(values))
end



bbind (print,_1,_2,true) (1,2)
-- 1	2	true
bbind (print,_2,_1,false) (1,2)
-- 2	1	false
bbind (print,_2,_1) (1,2)
-- 2	1
bbind (print,10,_1,20) (1)
-- 10	1	20