Lua - Making Table Callable



Some time we need to create function like objects. Lua provides a special metamethod __call. If __call is present in the associated metatable of the main table, then we can treat the table as argument. This is a useful in following cases −

  • Callable Object − object or table can be called similar to a function with any number of parameters.

  • Delegation − we can call different object or function when a table is called as a function.

Lua calls the implementation function of __call metamethod when a table is called as a function. If __call is not present or metatable is not defined at all then Lua will throw an error. Let's check each scenario with help of examples.

Example - Calling a table as function without __call metamethod

In case, we're not having __call metamethod for the table, Lua will throw an error as shown in example below −

main.lua

-- table 1
local table1 = { a = 1}

-- call table as a function
print(table1()) 

Output

When we run the above program, we will get the following output−

lua: main.lua:5: attempt to call a table value (local 'table1')
stack traceback:
    main.lua:5: in main chunk
    [C]: in ?

Example - Implementing __call metamethod

In below example, we've a more relevant example where we are implementing a __call metamethod to create a counter using table. When a table is called without any parameter, it returns the current counter incremented by 1. If any value is passed while calling the table, then that value is used as a base for the counter as shown below −

main.lua

-- create a table counter
local counter = { value = 0 }

-- metatable for callable table
local meta = {
   -- implement __call metamethod
   __call = function(table, base)
      table.value = table.value + (base or 1)
      return table.value
   end
}

-- set the metatable
setmetatable(counter, meta)

-- prints 1
print(counter())     

-- prints 6
print(counter(5))

-- prints 7
print(counter()) 

Output

When we run the above program, we will get the following output−

1
6
7
Advertisements