Function

From ComputerCraft
Jump to: navigation, search

A function is an encapsulation of code into a named chunk that can be reused and executed more than once. This is useful for seperating actions of a program that are written often into their own section to remove redundancy, boost code quality, and improve maintainability. Even if a section of code is only used once, if it is sufficiently complex or intricate (A good measure of this is often cyclomatic complexity), often it can be helpful to abstract those actions into their own function.

In Lua, functions are first class values, which means that functions are treated like any other value, like 2, true, or "String" with regards to how one can store and create them. Specifically this means that one can assign a function to a variable, pass a function as an argument, or return a function from another function.

To define a function, state the keyword function (optionally preceded by local to lexically localize it as opposed to defining it globally) followed by a name, and then a set of parentheses optionally containing a list of arguments (essentially local variables) that will be given to the function's environment when called. To return one or more values from a function, use the keyword return followed by a comma seperated list of the values/variables to return.

Warning Warning: Using return will stop execution of the function, anything after a return is evaluated will not be run, and (if it is in the same block as the return) is a syntax error.

Functions are called, which means to execute their contents, by stating their name followed by a set of parentheses, optionally containing any arguments (values) that you wish to pass along. When the function returns back to where it was called, it may return any amount of values, including 0.

Note Note: Strictly speaking, the method of defining a named function as described above is syntactic sugar for the following statement:

local myFunc; myFunc = function(myArg, myOtherArg) --[[Do some code]] end

-- Which is equivalent to:
local function myFunc(myArg, myOtherArg)
  -- Do some code
end

Which means that if you forward declare a variable for your function (that is to say, write local myFuncName before the actual definition of the function) you should not use the local keyword, as the variable it will be stored in is already localized. For example:

local myFunc -- Forward declaration

-- Maybe do or setup some other stuff, myFunc is in scope here

function myFunc(myArg, myOtherArg)
  -- Do some other code
end

The function myFunc in the above snippet is lexically scoped to where the forward declaration was written because the declaration merely assigned a value to the previously defined variable myFunc. This is semantically equivalent to the following snippet:

local myVar

-- Maybe do something, maybe involving myVar

myVar = 5

Examples

For example, let's define a function that will add 5 to the passed argument and then return it.

local function addFive(n)
  return n + 5
end

Now, we can call our function (in the same scope as that we declared it) by it's name:

local number = 8
number = addFive(number)
print(number) -- prints 13

Functions can also call other functions, like print(), for example:

local function coolFunction(thing)
  print("I am coolFunction and I was just called!")
  print("By the way, you passed", thing, "to me.")
end

coolFunction("Hello World")

Output:

I am coolFunction and I was just called!
By the way, you passed Hello World to me.

Functions can also be called multiple times. Take this example below:

local function myFunction()
  print("Hello World!")
end

myFunction()
myFunction()
myFunction()

Output:

Hello World!
Hello World!
Hello World!

Functions can also call themselves, this is called a recursive function:

local function fibRecursive(a, b, n)
  if n > 0 then
    return fibRecursive(b, a + b, n - 1)
  else
    return a
  end
end

local function fibonacci(n)
  return fibRecursive(0, 1, n)
end

print(fibonacci(7))  -- 13
print(fibonacci(12)) -- 144

Warning Warning: Improper recursion can result in runtime errors when the call stack is exceeded. Always remember to use proper tail calls wherever possible when using recursion.


Due to the first class nature of functions, they can even be arguments of other functions. For example:

local function applyHelloWorld(func)
    func("Hello World!")
end

-- Pass Lua's builtin print function...
applyHelloWorld(print)

Output:

Hello World!