Lua modules based on the Scribunto/Lua extension are stored in resource pages using the Module: namespace. Each module uses a table to hold functions and variables, and that containing table is returned at the end of the module code.[1] This lesson will show you how to troubleshoot script errors and handle run-time errors in your scripts.

Prerequisites

edit

This lesson assumes you have already completed the Tables lesson.

Create a Lua Script with Errors and Error Handling

edit

To create a Lua script with errors and error handling:

  1. Navigate to Module:Sandbox.
  2. Clear all existing code.
    It's a sandbox. Everyone is free to play in the sandbox. But if you find another user is actively editing the sandbox at the same time, you may also use Module:Sandbox/Username, where Username is your Wikiversity username.
  3. Add the following code and save the page:
local p = {}
 
local function reciprocal1(value)
    return 1 / value
end
 
function p.test1(frame)
    local value = frame.args[1]
    return reciprocal1(value)
end
 
local function reciprocal2(value)
    if value == nil then
        error('value must exist')
    end
    if tonumber(value) == nil then
        error('value must be a number')
    end
    if tonumber(value) == 0 then
        error('value must not be 0')
    end
    return 1 / value
end
 
function p.test2(frame)
    local value = frame.args[1]
    return reciprocal2(value)
end
 
local function reciprocal3(value)
    assert(value, 'value must exist')
    assert(tonumber(value), 'value must be a number')
    assert(tonumber(value) ~= 0, 'value must not be zero')
    return 1 / value
end
 
function p.test3(frame)
    local value = frame.args[1]
    return reciprocal3(value)
end
 
function p.test4(frame)
    local value = frame.args[1]
    if pcall(function () result = reciprocal3(value) end) then 
        return result
    else
        return 'Error: Value must exist, must be numeric, and not zero.'
    end
end
 
return p

Test Your Lua Script

edit

To test your Lua script:

  1. Navigate to either the Module_talk:Sandbox page, the Wikiversity:Sandbox page, or your own user or sandbox page.
  2. Add the following code and save the page:
;Reciprocal 1
:{{#invoke:Sandbox|test1}}
:{{#invoke:Sandbox|test1|x}}
:{{#invoke:Sandbox|test1|0}}
:{{#invoke:Sandbox|test1|2}}
;Reciprocal 2
:{{#invoke:Sandbox|test2}}
:{{#invoke:Sandbox|test2|x}}
:{{#invoke:Sandbox|test2|0}}
:{{#invoke:Sandbox|test2|2}}
;Reciprocal 3
:{{#invoke:Sandbox|test3}}
:{{#invoke:Sandbox|test3|x}}
:{{#invoke:Sandbox|test3|0}}
:{{#invoke:Sandbox|test3|2}}
;Reciprocal 4
:{{#invoke:Sandbox|test4}}
:{{#invoke:Sandbox|test4|x}}
:{{#invoke:Sandbox|test4|0}}
:{{#invoke:Sandbox|test4|2}}

The result should be similar to:

Reciprocal 1
Script error
Script error
inf
0.5
Reciprocal 2
Script error
Script error
Script error
0.5
Reciprocal 3
Script error
Script error
Script error
0.5
Reciprocal 4
Error: Value must exist, must be numeric, and not zero.
Error: Value must exist, must be numeric, and not zero.
Error: Value must exist, must be numeric, and not zero.
0.5

Understand Your Lua Script

edit

To understand your Lua script reciprocal1 function:

  1. local function reciprocal1(value) declares a local function named reciprocal1 that accepts a single parameter value, which is the value whose reciprocal will be returned.
  2. return 1 / value returns the reciprocal of value.
  3. end ends the function.

To understand your Lua script test1 function:

  1. function p.test1(frame) declares a function named test1 that accepts a single parameter frame, which is the object used to access parameters passed from #invoke.
  2. local value = frame.args[1] defines a local variable named value and assigns the value of the first frame argument (parameter) passed with #invoke.
  3. return reciprocal1(value) calls the reciprocal1 function, passing the variable value and returns the result.
  4. end ends the function.

To understand your Lua script reciprocal2 function:

  1. local function reciprocal2(value) declares a local function named reciprocal2 that accepts a single parameter value, which is the value whose reciprocal will be returned.
  2. if value == nil then creates a conditional code block and tests to see if value is nil. If it is, an error is generated.
  3. error('value must exist') generates an error with the given literal string as the error statement. Using error() allows the script writer to determine the text of the error message that is returned to the calling function or wiki page that invoked the function.
    When an error is generated, execution immediately returns to the calling function. Any additional code in the same function that comes after the error is not processed.
  4. if tonumber(value) == nil creates a conditional code block and tests to see if value is numeric. If it is not, tonumber returns nil and an error is generated.
  5. if tonumber(value) == 0 creates a conditional code block and tests to see if value is 0. If it is, an error is generated.
  6. return 1 / value returns the reciprocal of value.
  7. end ends the function.

To understand your Lua script test2 function:

  1. function p.test2(frame) and the following code declares a function named test2 that accepts a single parameter frame, which is the object used to access parameters passed from #invoke.
  2. local value = frame.args[1] defines a local variable named value and assigns the value of the first frame argument (parameter) passed with #invoke.
  3. return reciprocal2(value) calls the reciprocal2 function, passing the variable value and returns the result.
  4. end ends the function.

To understand your Lua script reciprocal3 function:

  1. local function reciprocal3(value) declares a local function named reciprocal3 that accepts a single parameter value, which is the value whose reciprocal will be returned.
  2. assert(value, 'value must exist') creates a self-contained conditional code block and tests to see if value is nil If it is, an error is generated.
    It is best practice to use assert to document and test any assumptions that are made regarding passed parameters.
  3. assert(tonumber(value), 'value must be a number') creates a self-contained conditional code block and tests to see if value is numeric. If it is not, tonumber returns nil and an error is generated.
  4. assert(tonumber(value) ~= 0, 'value must not be zero') creates a conditional code block and tests to see if value is 0. If it is, an error is generated.
  5. return 1 / value returns the reciprocal of value.
  6. end ends the function.

To understand your Lua script test3 function:

  1. function p.test3(frame) and the following code declares a function named test3 that accepts a single parameter frame, which is the object used to access parameters passed from #invoke.
  2. local value = frame.args[1] defines a local variable named value and assigns the value of the first frame argument (parameter) passed with #invoke.
  3. return reciprocal3(value) calls the reciprocal3 function, passing the variable value and returns the result.
  4. end ends the function.

To understand your Lua script test4 function:

  1. function p.test4(frame) and the following code declares a function named test4 that accepts a single parameter frame, which is the object used to access parameters passed from #invoke.
  2. local value = frame.args[1] defines a local variable named value and assigns the value of the first frame argument (parameter) passed with #invoke.
  3. if pcall(function () result = reciprocal3(value) end) then creates a conditional code block that calls the reciprocal3 function, passing value and storing the result. If no error occurs, result is returned. If an error occurs, a literal string is returned instead.
  4. pcall() uses the pcall (protected call) function to call a function and catch any errors that occur.
  5. function () ... end creates a self-contained anonymous function that executes the code in ... as a function call.
    The anonymous function is necessary to save the result of the reciprocal3 function while also using pcall() to catch any errors that occur.
  6. end ends the function.

Conclusion

edit

Congratulations! You've now created, tested, and understood a Lua script with error handling. Continue on to the Math Library lesson or return to the main Lua page to learn about other Lua code libraries.

See Also

edit

References

edit