Sunday, 5 March 2017

Lua Error Handling

Like many things in Lua, error handling is simple and straightforward and a little different from many languages. I am writing these simple notes to act as a reminder of those differences.  

There are two functions in Lua that allow you to trap errors, pcall and xpcall. The 'p'  seems to stand for protected, I haven't been able to make a good guess as to the 'x'. The difference between the two is that xpcall allows you to supply your own error handling function.

The main difference is that pcall and xpcall are functions rather than statements. You need to pass the code you wish to protect to them as an argument. You can't just wrap your code in try blocks as you can in many languages. You can't pass code blocks (chunks in Lua terminology) as function arguments in Lua. You need to wrap the code in a function. (It can be anonymous.)

A consequence of this is that you need to remember to pass the function and not the result of the function. A mistake that I found easy to make:
    > function f() return 1 end
    > =pcall(f())
    false attempt to call a number value

It should have been:
    > =pcall(f)
    true 1

You have probably noticed that pcall returns multiple values, the first is a status (true for okay, false if an error occurred) and then either the values returned from your function or from the error function. For example:
    > function fe() error('there was an error') end
    > =pcall(fe)
    false stdin:1: there was an error

You pass arguments to your function by supplying them as additional arguments to pcall:
    function errDemo (i, j) 
      if 'number' ~= type(i) or 'number' ~= type(j) then 
        error{msg='catch this'}
      return i, j

    > =pcall(errDemo, 1, 2)
    true       1 2
    > status, err = pcall(errDemo, "1", 2)
    > =status
    > =err.msg
    catch this

Lastly, xpcall takes an additional function, passed as second argument, that will be called when an error occurs. It is passed object that is returned by the error function. Here is a simple example:
    > function handleError (err) return 'caught you' end
    > =xpcall(errDemo, handleError, "1", 2)
    false caught you

No comments: