Functions in Lua

1. Introduction

In previous pages in this sequence you have seen how to control Lua and write programs with loops and variables. This page introduces you to how to define functions in Lua and the idea of local variables.

As usual, all of the Lua described on this web page has analogues in just about any other standard "imperative" programming language such as C++, Java, C# etc. It will take very little time to convert what you learn about Lua to some other language.

(If you are reading the manual at https://www.lua.org/pil/contents.html you will come across much more about functions. There are a number of "advanced" features to do with functions (such as functions being "first class objects" and about "closures") which are not always translatable across to other languages. In these respects, Lua is rather sophisticated but this level of sophistication is not needed for maths modules in Birmingham and reading beyond Chapter 5 of the Lua book is only for people that are particularly interested in it.)

2. Functions

Functions in mathematics are rather ubiquitous and we are all familiar with the idea of "the function x 2 ", and "the function sin x " for example. The same ideas apply to computer programming and they are just as useful there. You need to be careful, however, of the number of (and type of) inputs to the function.

So for example "the function x 2 " really has a single input x and would be written in Lua as

function square(x)
  return x*x
end

Try it:

> function square(x)
>> return x*x
>> end
> print( square(2) )
4
>

Note that the name of a function can be any sort of name that you can give to a variable, and in general it is better to give a function a long descriptive name rather than a short and obscure name.

You have to tell the computer what the input(s) to the function is(are). It won't be able to guess, since if you simply use a variable name it will assume that the variable is a global variable.

function test(y)
  return x+y*y
end

Try it:

> function test(y)
>> return x + y*y
>> end
> x = 3
> test(4)
19
> x = -1
> test(5)
24
> y = 3
> test(2)
3
>

The values x = 3 and x = -1 are used as parameters to the function "test". The input to the function is y (not x) because the function is defined as "function test(y)". In the last two lines, "y = 3; test(2)" the computer sets the input y to "test" as being 2 (not 3) and calculates -1 + 2*2 (since at this point the variable x is still -1).

Notice that this means there are two variables called "y", the "local" variable inside the function "test", and the global variable "y" which is initialised to 3 but never used at all.

If you want to have more than one input to a function, just list them, separated with commas.

Of course the body of the function is just that - a body, and can contain several Lua statements, including loops.

function sum(r,s)
  ans = 0
  for x=r,s do
    ans = ans + x;
  end
  return ans
end

Try it:

> sum(1,10) 
55
> sum(1,100)
5050
>

3. Local variables

There is a serious problem with the previous program for the sum of the integers from r to s.

> ans = 4
> sum(1,10) 
55
> print(ans)
55
>

Where did the old value ans = 4 go?

If the calculation was inside another function or another calculation this is quite probably not what is required. For example, to calculate s = 1 10 j = 1 s j one might write,

function sum(r,s)
  ans = 0
  for x=r,s do
    ans = ans + x;
  end
  return ans
end

function outersum(n)
  ans = 0
  for s=1,n do
    x = sum(1,s)
    ans = ans + x
  end
  return ans
end

print( outersum(10) )

The answer printed is incorrect. (It prints 110 not 220.)

The problem is that the variable "ans" in the two functions is the same one and the intermediate value in "outersum" is destroyed when "sum(1,s)" is called.

The solution is to make the two variables "ans" different and local to their functions. The keyword to do this is "local". While we are at this, we should also make the temporary variable x local too.

function sum(r,s)
  local ans = 0
  for x=r,s do
    ans = ans + x;
  end
  return ans
end

function outersum(n)
  local ans = 0
  for s=1,10 do
    local x = sum(1,s)
    ans = ans + x
  end
  return ans
end

print( outersum(10) )

Recall that Lua automatically makes the variables in a "for" loop local in the same way, and the "inputs" to functions (such as r,s,n above) are also local. The "local" keyword can make a variable local to any block of code, including a loop or the body of an if statement, but it is usally used to make a variable local to a function.

Normally you write part of a program, with a view to extending it or expanding it later. You do not know exactly how your program will be extended, or who will do it, or what variables might be used in that extension. Therefore it is important to write in such a way that the person using and extending your code will have as few nasty surprises as possible. Therefore,

Always make variables local to the smallest possible region of code, unless you have very strong reasons to do otherwise. Limit the number of "global" variables to as small as possible (ideally none).

Exercise: Define a Lua function s(n) that calculates the value, i = 1 n j = 1 i ( i + j ) 2 .