Lua - how to decorate a function?

I’m looking for some solution to the problem:

create_update_handler(params)
 return function()
  if params.a then ... end
  if params.b then ... end
  ...
 end 
end

function init()
 self.update_handler = create_update_handler(params)
end

function update()
  self.update_handler()
end

I want to create many versions of one function (“update_handler()”) that will be used in update(), but when I choose how this handler will look like in init(), then I would like to use that version all the time, without checking for all if in that function.

Ideally, I was thinking about using it in a render_script - so I setup how I would like my update function to look like once, in init (or maybe even in on_message sometimes) and then I use such factored function, so that’s why I want to get rid of any ifs in the update.

I think that decorator pattern could be something to go here, but I really would like to have a “static” version of update_handler (I mean, after I set up, what needs to be handled every update, in the beginning = in init). Should I use metamethods here? Am I thinking in a correct way?

I’m not sure, but maybe it will be useful

local t = {
    first = function(params)
        --Do something if id is first
    end,
    second = function(params)
        --Do something if id is second
    end
}
function init()
    self.state = "first"
end

function update()
    t[self.state](params)
end
1 Like

You’ve got the right idea using the higher-order-function pattern. Remember that in Lua functions are values, so you can do something like this:

local function create_update_handler(params)
  if params.a then
    return function () ... end
  elseif params.b then
    return function () ... end
    ...
  else
    return function () ... end
  end
end

function init()
 self.update_handler = create_update_handler(params)
end

function update()
  self.update_handler()
end

This way, the check is only done once at update handler creation time

3 Likes

Thanks @Denis_Makhortov! I was thinking about something like this as well, however I would like to have a function in a local value, not a table,but if it would not be such a bottleneck, it is pretty convenient option!

@dapetcu21, thanks! This is true, nonetheless what in a case, where I would like to make it even more convenient to create and “add” /“concatenate” functions that handle some part and build and output function consisting of such “blocks”. That’s why I thought about decorating. I was thinking, if there is a smart way to make a function consisting of some parts I will choose in init and not to create functions for each combination of params. For example - you want to render GUI generally in the same way, but render tiles or particles to some render target, sometimes it could be needed to use more than one render target, etc. And I don’t want to decide about it in every update call, saving the crusial miliseconds :smile:

I will try to experiment and see what is the best solution and will share results with you here :wink:

“Decorating” can be easily done with higher order functions as well. Check this out:

local function with_cats(f)
  return function (self, dt)
    print("Meow!")
    return f(self, dt)
  end
end

local function with_dogs(f)
  return function (self, dt)
    print("Woof!")
    return f(self, dt)
  end
end

update = with_cats(with_dogs(function (self, dt)
  print("Just your usual update()")
end))

With a bit of luck, that final return would also enable tail call optimisation in LuaJIT, so it should be pretty low cost.

2 Likes

This is a solution I was thinking about! :wink: Thanks! :100:

I see what you did there.

4 Likes