PICO-8 Generic Dispatch with Parameters

PICO-8 has this nice helper function called foreach(table, func) which will call the function for each item. I like to use this in my _draw function to dispatch drawing to game objects. The trouble is that most of the time I want to call a method (table-bound function) instead of a function. Normally this required a helper function per-method to invoke.

Consider the following PICO-8 code (it’s just Lua with some sugar).

-- returns a table with table-bound method 'draw'
function dot(x, y)
 return {x=x, y=y,
  draw=function(self,col)
   local c=col or 7
  	pset(self.x,self.y,c)
  end
 }
end

-- returns a function with captured upvalues
function dot2(x, y)
 return function(col)
  local c=col or 7
  pset(x,y,c)
 end
end

function _init()
 drawable={}
 add(drawable, dot(64, 64))
 add(drawable, dot2(64, 68))
end

In this example, I’m showing two different ways to make “drawable” instances. dot returns its instance as a table with a method named draw. dot2 returns a function which draws itself when invoked. I’ll start with the dot2 case.

function invoke(o)
 o()
end

function _draw()
 cls()
 foreach(drawable, invoke)
end

The nice thing about the approach of making drawable a function closure is that you can make a generic invoke helper function which just calls instance. This means you only need a single helper function. The downside is that you can only return one callable behavior this way which isn’t ideal for more complex objects.

function call_draw(o)
 o:draw()
end

function _draw()
 cls()
 foreach(drawable, call_draw)
end

This approach is more flexible and allows for more methods to be defined, but now you need a call_foo helper for each different method to call. Another problem with both approaches is you can’t pass in arguments to the method calls.

It turns out that Lua gives us a ton of flexibility to build our generic dispatch. Let’s start with the problem of dispatching by name.

-- Call Method
function callm(method)
 return function(o)
  o[method](o)
 end
end

function _draw()
 cls()
 foreach(drawable, callm("draw"))
end

callm is a pretty simple helper. The core of it just does a table lookup by name and invokes the result. callm returns a function because foreach expects a function that takes the object being iterated. There are a few problems with this approach. First this crashes if there isn’t a draw method on the instance. Second, the dot.draw method takes an argument and there’s no way to pass one in.

-- Call Method
function callm(method, ...)
 local params={...}
 return function(o)
  if type(o)=="table" then
   local m=o[method]
   if type(m)=="function" then
    m(o,unpack(params))
   end
  end
 end
end

function _draw()
 cls()
 foreach(drawable, callm("draw", 10))
end

This version adds support for varargs that get forwarded to the method when the returned function is called. This allows parameters to be passed to the method. This also adds some type checking to ensure the instance passed in is a table and has a function named method. You can see the foreach call site looks pretty good.

Finally, if you want to continue to use callable objects instead of tables, we can take this same concept and make it work with those too.

-- Call function 'object'
function call(...)
 local params={...}
 return function(o)
  if type(o)=="function" then
   o(unpack(params))
  end
 end
end

function _draw()
 cls()
 foreach(drawable, call(10))
end

Final thoughts

This adds overhead to the calls, and it’s almost certainly more efficient to use for x in all(XS). That said, it’s a neat little piece of code and I think it’s pretty cool that it can be accomplished with Lua.

Try out the code.
function _init()
 game_items={}
 -- add items
end

function _update()
 -- call 'update' on each instance that implements it
 foreach(game_items, callm('update')
end

function _draw()
 -- call 'draw' on each instance that implements it
 foreach(game_items, callm('draw')
end

Class Modules in Lua

I’ve been playing around with the Löve2D game engine as part of a side project. It’s a 2D engine that uses Lua for its scripting. Part of trying it out meant getting familiar with Lua.

Lua is an interesting little language. Very simple in its syntax, but also quite flexible and extensible. Out the box, the language offers very little OOP capability. There’s some special syntax to automagically declare and pass around a this (self in Lua) reference, but other than that is definitely “roll your own”.

If you’re not familiar with Lua, here’s a quick primer. Everything is represented by a table (think dictionary/associative array). Basically you create a reference to a table. The table can contain named values and values can be functions.

x = { a = 5 } creates a table referred to by x which has a single member a that has the value 5. You can get and set the value of a like this print(x.a) or x["a"] = 5. It’s a lot like JavaScript in that regard.

You can also store functions in tables.
x = { sayHi = function() print("hi") end }
You can call the function like this x.sayHi()

If you want to build an “object” you can do something like this:
obj = {val = 0, incr = function(self) self.val = self.val + 1 end }
In this example, we’ve created a table that holds a value and a “method”, incr, that acts on the object. To call incr you must either pass in the object ref like this obj.incr(obj) or use the special colon syntax obj:incr() which will automatically pass in the containing table as the first parameter.

You’ll also need to know about metatables, specifically the __index metamethod, to really understand the rest of this post.


Disclaimer: I’ve been programming professionally for years, but I’ve only been messing around with Lua for about a week.

If you search for “Lua class modules” online, the top two hits are two blogs with two very different approaches to creating modules that export OO types. Hisham’s guidelines for writing Lua modules and catwell’s response to that post.

After reading both, I prefer catwell’s approach because of the flexibility around implementation hiding and ease of changing the interface that the module exports. The examples in his post had one problem that I didn’t like: the approach of setting anonymous metatables makes implementation of metamethods clunky because they are defined separately from the rest of the methods. His approach has a benefit that because the metatable is anonymous, the internal implementation is safe from tampering because the method table itself is not directly exported (you can still get it though). There’s another option to protect the method table from monkey patching using metatable hiding which is how I address the problem below.

To demonstrate my approach, I’m going to walk through a table-based implementation of a Counter class module. The explanation will be in the code comments.

-- First, I pre-declare a table that will act as both
-- the method table and the metatable. I do this because
-- I like to define my 'new' function before the other
-- functions so it's available if I want to return new
-- objects from within other functions in the module
local mt = {}

-- Next, define all of the module functions as local
-- functions. Doing it this way instead of directly
-- hanging the methods off of the class table, allows
-- for more flexibility to modify the internal
-- implementation separate from the exported interface.
-- This is aligned with catwell's approach.

-- Define the 'new' function. The member fields are
-- also defined here. Notice that that I'm setting the
-- metatable to mt (that's why it needed to be pre-decl'd)
local new = function(val)
  local obj = {
    val = val or 0
  }

  return setmetatable(obj, mt)
end

-- Define the increment function. Notice I'm not using
-- colon syntax here for the reasons catwell outlined.
local incr = function(self)
  self.val = self.val + 1
end

-- Define a tostring function
local tostring = function(self)
  return string.format("Counter is %d", self.val)
end

-- Now that the implementations are defined, we can add
-- them to the method table. This also gives you a nice
-- place to refine the interface you want to export.
-- E.g. I will export 'incr' as 'increment'.
mt.increment = incr

-- If the class had more methods, they would be
-- exported here. Because I'm also using mt for a
-- metatable, I can export metamethods too.
mt.__tostring = tostring

-- Now that the interface has been defined, I need to
-- set up the metatable. First the metatable needs to
-- use itself for method lookup.
mt.__index = mt

-- Next, because we don't want the method table to be
-- tampered with, hide the metatable. This line will
 -- make getmetatable(x) return an empty table instead
-- of the real metatable. If we didn't do this, consumers
-- could get the metatable and because it's also the method
-- table, could monkey patch the implementation.
mt.__metatable = {}

-- That's pretty much it. I also add a 'constructor'
-- to forward the arguments to the 'new' function.
local ctor = function(cls, ...)
  return new(...)
end

-- Finally return a table that can be called to get a new
-- object. You could also simply return a function or a
-- table with a 'new' member. It's all a matter of style and
-- what syntax you want your consumers to use.
return setmetatable({}, { __call = ctor })

You use my new class module like this (in the Repl).

> Counter = require "counter"

> c = Counter()
> print(c)
Counter is 0

> c:increment()
> print(c)
Counter is 1

> c2 = Counter(100)
> print(c2)
Counter is 100

Pretty straight-forward. Notice I’ve made two instances, one that that was initialized with the default and one initialized with 100. You can see that they each have their own value that can be incremented independently using the exported name ‘increment’ (as opposed to the defined function ‘incr’). Also notice that the meta method __tostring is defined and is forwarded to the internal implementation of tostring.

Now lets test how “safe” it is. First let’s try overriding ‘increment’ on one of the objects and verify it doesn’t affect the other. I’m overriding the behavior on instance ‘c’ to increment by 10.

> c.increment = function(self) self.val = self.val + 10 end
> c:increment()
> print(c)
Counter is 11

> c2:increment()
> print(c2)
Counter is 101

Good. It only affects instance ‘c’. How about if we try to explicitly patch the method on the method table? You can usually get a reference to that table by getting the __index instance from the method table.

> =getmetatable(c).__index
nil

Can’t do that either because the metatable is hidden (by setting the __metatable metamethod).


To recap, I prefer the module style described by in catwell’s blog because it allows you to more formally export an interface that isn’t directly tied to the implementation. Also, it promotes simpler function design and better implementation hiding. The difference between my approach and catwell’s only really differs in the mechanism of hiding the method table. By combining the metatable and method table instead of using an anonymous metatable, it’s clearer and cleaner when defining metamethods. This is especially useful when defining metamethods like __add and __eq.

That said, I would not consider myself an adept Lua programmer. If I’ve overlooked something, please help me learn by leaving a comment below.