Function Call Tutorial

lua-users home

This tutorial follows on from the FunctionsTutorial.

Passing arguments

Since Lua is dynamically typed and has no need for function type declaration, checking the number and type of arguments required for a function seems somewhat redundant. Lua deals gracefully with mismatched numbers of calling and formal function arguments. Formal function arguments receive a default value of nil if they are not filled. Where too many arguments are passed they are simply ignored. No type is specified for each argument as they are dynamically typed. i.e. we only need to know the type of an object when we use it, not when we reference it. We'll use the following function as an example:

> function foo(a,b,c) print(a,b,c) end
Here's what happens when we call it with no arguments:
> foo()
nil     nil     nil
Notice that each of the arguments defaulted to the value nil, or no value, and we don't get an error. Here's what happens when we pass too many arguments:
> foo(1,2,3,4)
1       2       3
Again, no error and the last argument is ignored. Because Lua is dynamically typed we can pass any argument type. e.g. we can pass strings in as well as numbers or references.
> foo("hello")
hello   nil     nil
> foo("pi", 3.1415, { comment="this is a table" })
pi	3.1415	table: 0x21d49b0

Variable arguments

It is often useful to have variable numbers of arguments to a function. e.g. the printf(format,...) function in C. One way Lua does this is by placing the variable argument list into an array table called arg, usable by the function. e.g.,

> function foo(...) print(arg) end
> foo("abc",3,77)
table: 0x21d56a0

Note: In 5.2 arg is deprecated and three periods (...) can be used instead with similar effect.

> function foo(...) print(...) end

(In some cases, the argument list array must be referenced by placing the three periods within a set of curly braces.)

> function foo(...) for k,v in pairs({...}) do print(k,v) end end

In this example we can only see that this is a table. We could use table.foreach(table,function) to print out the values of the variable argument table, but using pairs() is better, since table.foreach() is deprecated in Lua 5.1.

> function foo(...) for k,v in pairs(arg) do print(k,v) end end
> foo()
n       0

From looking at an empty variable argument list it is easy to see that an extra table pair is added to provide the number of elements in the table, arg.n. In this case the number of arguments is zero. Let's try passing variable numbers of arguments:

> foo(1,2,3)
1       1
2       2
3       3
n       3
> foo("apple",2,"banana",99,3.1415927,foo)
1	apple
2	2
3	banana
4	99
5	3.1415927
6	function: 0x9ecd20
n	6

Another way is to use ... as a placeholder:

> function foo(...) print('x', select(2, ...), 'y', ...) end
> foo("apple", "banana", "orange")
x	banana	y	apple	banana	orange

The ... has an additional advantage in that it avoids the small performance penalty in constructing the arg table.


A useful function for variable arguments is unpack(). This takes a table and returns a list of variables, e.g.:

> = unpack({1,2,3})
1       2       3

This can be used with variable argument lists as follows:

> function listargs(...)
>>  return unpack(arg)
>> end
> = listargs({1,2,3})
1       2       3
> = listargs({"hello", {1,2,3}, function (x) return x*x end})
hello	table: 0x9efed0	function: 0x9eec40

It can also be used to pass a variable number of arguments to a function as follow:

> function countargs(...)
>>  return #arg
>> end
> = countargs(1,2,3)
> = countargs(unpack{1,2,3})

To understand how unpack works, look at this slow pseudo implementation:

>    function unpack (t, i)
>>      i = i or 1
>>      if t[i] ~= nil then
>>>        return t[i], unpack(t, i + 1)
>>      end
>    end

Taken from the lua reference manual: [chapter 5.1 - Multiple Results].

Multiple return values

Lua can return more than one value from a function. This is done by returning a comma separated list of values:

> function foo(angle)
>>  return math.cos(angle), math.sin(angle)
>> end
> print( foo(1) )     -- returns 2 values...
0.54030230586814        0.8414709848079
> c,s = foo(3.142/3)  -- assign the values to variables
> = math.atan(s/c)
> = c,s
0.49988240461137        0.86609328686923
> function many(x)
>>  return x, x*x, x*x*x, x*x*x*x, x*x*x*x*x
>> end
> = many(5)
5       25      125     625     3125
> = many(0.9)
0.9     0.81    0.729   0.6561  0.59049

The above function could have a variable number of return values if we construct a table, containing the values, and use unpack. E.g.,

> function many2(x,times)
>>  local t = {}
>>  for i=1,times do t[i] = x^i end
>>  return unpack(t)
>> end
> = many2(5,10)
5       25      125     625     3125    15625   78125   390625  1953125 9765625
> = many2(0.5,7)
0.5     0.25    0.125   0.0625  0.03125 0.015625        0.0078125

Values as a table

We can also return the values in a table. To do this we add curly brackets around the function call, which will construct a table, i.e.:

{ function_name ( args ) }

Here is an example using the previous function example:

> = { foo(1.5) }
table: 0x204e100
> t = { foo(1.5) }
> for k,v in ipairs(t) do print(k,v) end
1       0.070737201667703
2       0.99749498660405

Single Value

If a function returns multiple values, but we only want the first value, we put a parenthesis around the function call, i.e.

( function_name ( args ) )
Here is an example:
> = (foo(1.5))
> = foo(1.5)
0.070737201667703       0.99749498660405

The same could be achieved by returning a table and taking the first element but the above syntax is more efficient. E.g.,

> = ({foo(1.5)}) [1]

RecentChanges · preferences
edit · history
Last edited April 5, 2013 12:40 am GMT (diff)