This first edition was written for Lua 5.0.
While still largely relevant for later versions, there are
some differences.
The fourth edition
targets Lua 5.3 and is available at Amazon and other bookstores.
By buying the book, you also help to support the Lua project.
Programming in Lua
Part I. The Language
Chapter 5. Functions
5.1 – Multiple Results
An unconventional, but quite convenient feature of Lua
is that functions may
return multiple results.
Several predefined functions in Lua return multiple
values.
An example is the string.find function,
which locates a pattern in a
string.
It returns two indices:
the index of the character where the pattern
match starts
and the one where it ends (or nil if it cannot find the pattern).
A
multiple assignment allows the program to get both results:
s, e = string.find("hello Lua users", "Lua")
print(s, e) --> 7 9
Functions written in Lua also can return multiple results,
by listing them all
after the return keyword.
For instance, a function to find the maximum
element in an array
can return both the maximum value and its location:
function maximum (a)
local mi = 1 -- maximum index
local m = a[mi] -- maximum value
for i,val in ipairs(a) do
if val > m then
mi = i
m = val
end
end
return m, mi
end
print(maximum({8,10,23,12,5})) --> 23 3
Lua always adjusts the number of results from a function to
the circumstances
of the call.
When we call a function as a statement,
Lua discards all of its
results.
When we use a call as an expression,
Lua keeps only the first result.
We get all results
only when the call is the last (or the only) expression in
a list
of expressions.
These lists appear in four constructions in Lua:
multiple
assignment, arguments to function calls,
table constructors, and return
statements.
To illustrate all these uses,
we will assume the following
definitions
for the next examples:
function foo0 () end -- returns no results
function foo1 () return 'a' end -- returns 1 result
function foo2 () return 'a','b' end -- returns 2 results
In a multiple assignment, a function call as the last (or only)
expression
produces as many results as needed to match the
variables:
x,y = foo2() -- x='a', y='b'
x = foo2() -- x='a', 'b' is discarded
x,y,z = 10,foo2() -- x=10, y='a', z='b'
If a function has no results, or not as many results as we need,
Lua produces
nils:
x,y = foo0() -- x=nil, y=nil
x,y = foo1() -- x='a', y=nil
x,y,z = foo2() -- x='a', y='b', z=nil
A function call that is not the last element in the list
always produces one
result:
x,y = foo2(), 20 -- x='a', y=20
x,y = foo0(), 20, 30 -- x=nil, y=20, 30 is discarded
When a function call is the last (or the only) argument to another call,
all
results from the first call go as arguments.
We have seen examples of this
construction already,
with print:
print(foo0()) -->
print(foo1()) --> a
print(foo2()) --> a b
print(foo2(), 1) --> a 1
print(foo2() .. "x") --> ax (see below)
When the call to foo2 appears inside an expression,
Lua adjusts the number
of results to one;
so, in the last line, only the "a" is used in the concatenation.
The print function
may receive a variable number of arguments.
(In the next
section we will see how to write functions with
variable number of
arguments.)
If we write f(g())
and f has a fixed number of arguments,
Lua
adjusts the number of results of g to the number
of parameters of f,
as we saw
previously.
A constructor also collects all results from a call,
without any adjustments:
a = {foo0()} -- a = {} (an empty table)
a = {foo1()} -- a = {'a'}
a = {foo2()} -- a = {'a', 'b'}
As always, this behavior happens only when the call is
the last in the list;
otherwise, any call produces exactly one result:
a = {foo0(), foo2(), 4} -- a[1] = nil, a[2] = 'a', a[3] = 4
Finally, a statement like return f() returns all values
returned by f:
function foo (i)
if i == 0 then return foo0()
elseif i == 1 then return foo1()
elseif i == 2 then return foo2()
end
end
print(foo(1)) --> a
print(foo(2)) --> a b
print(foo(0)) -- (no results)
print(foo(3)) -- (no results)
You can force a call to return exactly one result by
enclosing it in an extra pair
of parentheses:
print((foo0())) --> nil
print((foo1())) --> a
print((foo2())) --> a
Beware that a return statement does not need parentheses around
the
returned value,
so any pair of parentheses placed there counts as an extra
pair.
That is,
a statement like return (f()) always returns one single value,
no matter how many values f returns.
Maybe this is what you want, maybe
not.
A special function with multiple returns is unpack.
It receives an array
and
returns as results all elements from the array,
starting from index 1:
print(unpack{10,20,30}) --> 10 20 30
a,b = unpack{10,20,30} -- a=10, b=20, 30 is discarded
An important use for unpack is in a generic call mechanism.
A generic call
mechanism allows you to call any function,
with any arguments, dynamically.
In ANSI C, for instance, there is no way to do that.
You can declare a function
that receives a variable number of arguments (with stdarg.h)
and you can
call a variable function, using pointers to functions.
However, you cannot call
a function with a variable number of arguments:
Each call you write in C has
a fixed number of arguments
and each argument has a fixed type.
In Lua, if
you want to call a variable function f
with variable arguments in an array a,
you simply write
f(unpack(a))
The call to unpack returns all values in a,
which become the arguments to f.
For instance, if we execute
f = string.find
a = {"hello", "ll"}
then the call f(unpack(a)) returns 3 and 4,
exactly the same as the static call
string.find("hello", "ll").
Although the predefined unpack is written in C,
we could write it also in Lua,
using recursion:
function unpack (t, i)
i = i or 1
if t[i] ~= nil then
return t[i], unpack(t, i + 1)
end
end
The first time we call it,
with a single argument, i gets 1.
Then the function
returns t[1]
followed by all results from unpack(t, 2),
which in turn returns
t[2]
followed by all results from unpack(t, 3),
and so on, until the last non-
nil element.
Copyright © 2003–2004 Roberto Ierusalimschy. All rights reserved.