[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Forward References - a Useful Pattern
- From: steve donovan <steve.j.donovan@...>
- Date: Wed, 17 Feb 2010 11:31:13 +0200
Hi all,
This hack du jour is for when you need forward references to a set of functions.
E.g.
mod = Forward()
funs = {mod.copy, mod.print, mod.eval}
function mod.print()
print 'printing!'
end
function mod._not_implemented (name)
print(name..' is not implemented')
end
for _,f in ipairs(funs) do f() end
==>
copy is not implemented
printing!
eval is not implemented
This is useful if say you are mocking up a user interface and want to
fill in all the functions; it also makes it easy to automatically
check whether all references have been satisfied.
This is done by making the __index function of our table create
references; when these are called, they forward to the actual
function, if available, otherwise produce a result which can be
customized by defining _not_implemented.
function Forward ()
return setmetatable({},forward_MT)
end
forward_MT = {
__index = function(mod,name)
local ref = forward_ref(mod,name)
mod[name] = ref
return ref
end
}
function forward_ref (mod,name)
return setmetatable({mod=mod,name=name},forward_ref_MT)
end
forward_ref_MT = {
__call = function(ref,...)
local fun = rawget(ref.mod,ref.name)
if type(fun) == 'function' then -- forward the call to the implementation
fun(...)
elseif rawget(mod,'_not_implemented') then -- wants to handle a miss...
mod._not_implemented(ref.name)
else
error("'"..ref.name .. "' is not implemented",2)
end
end
}
steve d.