Wednesday, February 12, 2014

The better and cleaner way to pass parameters to event handlers in Corona SDK

Corona SDK has simple event and easy to use event mechanism.  For example, if you want to do something after 1 second delay, you would do this:


function handler(event)
  -- do something
end 

timer.performWithDelay(1000, handler)

However, if you want to pass arguments to the handler, you can either use closure or attach those arguments to the timer object itself, both of these method are described in performWithDelay API document.

However, both of them are not very clean and very specific to each instance of the event.  The better way to doing this is to use the so-called curry function.

Curry function is a little trick used frequently in functional languages.  Basically it transforms a function with n arguments into a new function with n-1 arguments.  Lua-user.org has a nice explanation if you are interested in details, but currying function posted there is very generic though.  Since we simply need it to pass parameters to event handlers, we can be a bit more specific to save a few keystrokes and make the code looks cleaner.

So, we write our currying function like this (you only need to write this once somewhere in your project)


function curry1(f, v)
    return function (y) return f(v,y) end
end

'1' in function name is there to remind us that it needs the first parameter for the function  f , which is about to be currified.

Then we write our handler like this

function handler(v, event)
   print(v)
end 

Notice that the handler now has two parameters.  We will pass our parameter to 'v', while 'event' will be populated by Corona event dispatcher.

The last step is to use it.  In case of performWithDelay, it looks like this


timer.performWithDelay(1000, curry1(handler, 10))

In this case, we pass number 10 to the event handler.  If you run it, '10' will be printed on the console after 1 second delay (if you need more than one parameters, simply use a table, see below).

Here's main.lua for you to copy-and-paste and play with


function curry1(f, v)
    return function (y) return f(v,y) end
end

function handler(v, event)
   print(v)
end 

function handler2(t, event)
   print(t.a)
   print(t.b)
end

timer.performWithDelay(1000, curry1(handler, 10))
timer.performWithDelay(2000, curry1(handler2, {a=1, b=2}))

enjoy

No comments:

Post a Comment