Search code examples
variablesluagloballocalmetatable

Why does this function run as a global variable, but not as a local one?


Defining 'eventHandlers.key_up' as global works, but defining it as local does not.

local event = require "event"

local running = true

local function unknownEvent()
    --
end

local eventHandlers = setmetatable({}, { __index = function () return unknownEvent end })

function eventHandlers.key_up(addr, char, code, playerName)
    if (char == string.byte(" ")) then
      running = false
    end
end

local function handleEvent(eventID, ...)
    if (eventID) then
        eventHandlers[eventID](...)
    end
end

while running do
    handleEvent(event.pull ())
end

This is an example event handler used by the OpenComputers mod for Minecraft. 'Event' is basically a library that pulls signals from the computer (in this case, keyboard input) and tells the computer what to do with the event.

The program basically waits at the loop at the bottom, listening for an event. This example listens for a 'key_up' event. The event also gives additional information, such as the keyboard address, the character pressed, the player who pressed it etc.

In this example, lifting the spacebar after being pressed (a 'key_down' event) breaks the loop at the bottom and the program terminates.

I'm relatively new to lua coding, and I can work my way around relatively straightforward code, however here I'm stuck. I have two questions:

(1) Why is it that this works when the 'eventHandlers.key_up' function is defined as global, but not when defined as local?

(2) What is the metatable's role in this code? I've been researching metatables and metamethods but I'm finding it quite the difficult topic to grasp.

Open Computers - API:Event

The error I get is this:

Line 11: '(' expected near '.'

Solution

  • The table eventHandlers is already local in scope, so:

    function eventHandlers.key_up(addr, char, code, playerName)
    

    … is adding a function to this local table. You can also do this:

    eventHandlers.key_up = function(addr, char, code, playerName)
    

    … which might make this a bit clearer.

    Re metatables: here setmetatable returns an empty table with a metatable containing the __index metamethod. The __index metamethod is called whenever you try to access a field that is not in the table.

    So here if you write eventHandlers.blah_blah(), Lua won't find blah_blah in the table, so will call this __index metamethod if it exists, which will replace blah_blah with unknownEvent and call it because we used parentheses.