Reputation: 652
I work a lot with Lua and Corona SDK, and while I love it as a language, I've realised that my code can get quite messy as callbacks call callbacks and so on.
I was wondering if there were any design patterns or libraries (like async.js for JavsScript) that help reduce the issue.
A typical example would be the use for Corona's transition call:
transition.to(obj,{... onComplete=function()
transition.to(obj,{... onComplete=function()
if foo then
transition.to(obj,{... onComplete=function() ... end})
else
transition.to(obj,{... onComplete=function() ... end})
end
end})
end})
I find that code quickly become quite dense, but that often inner closures rely on variables from the outer ones. I appreciate that self-discipline is an important factor in creating clean code, but it's useful to have a structure to impose using self-discipline. Other than naming closures has anyone come across a useful way of managing this?
Upvotes: 1
Views: 3009
Reputation: 97631
Using coroutines might help here:
await = function(f)
return function(...)
local self = coroutine.running()
f(..., {onComplete=function(...)
coroutine.resume(self, ...)
end})
return coroutine.yield()
end
end
await(transition.to)(obj)
await(transition.to)(obj)
if foo then
await(transition.to)(obj)
else
await(transition.to)(obj)
end
Or perhaps more generically, addressing the issue in the comments:
async_call = function(f)
local self = coroutine.running()
local is_async
local results = nil
local async_continue = function(...)
if coroutine.running() ~= self then
is_async = true
coroutine.resume(self, ...)
else
is_async = false
results = {...}
end
end
f(async_continue)
if is_async then
return coroutine.yield()
else
return unpack(results)
end
end
async_call(function(cont) transition.to(obj, {onComplete=cont}) end)
Upvotes: 2
Reputation: 10512
One way is to define the callback as a global or upvalue and inject the upvalues the callback would need into it by wrapping the callback in another function:
function foo(upvalue)
return function(...) -- thats the actual callback
return print(upvalue, ...);
end
end
Then you can just attach it as a callback like
transition.to(obj,{... onComplete=foo(somevar)})
The additional function call will however have some small impact on performance. On the other hand, if you have multiple similar callbacks, you could probably come up with some kind of code reuse.
Upvotes: 0