You have been calling functions since the first lesson: print, io.read, tonumber. In this lesson you write your own, and then put everything from this unit together in one complete program.
A function is a named step
A function is a block of statements with a name. Writing the block and naming it is called defining the function. Running it is called calling it.
local function show_rule()
print("--------------------")
end
show_rule()
print("Today's menu")
show_rule()This prints a line of dashes, then Today's menu, then another line of dashes.
The first three lines define the function. They start with local function, then the name, then a pair of round brackets, and they finish with end. The statements in between are the function's body. As with variables, local keeps the name to this file. Defining a function runs nothing: no dashes appear until a later line calls it with show_rule().
Lua reads the file from top to bottom, so a function must be defined above the first line that calls it.
Functions are worth writing for two reasons. A step you need several times is written once. And a well-chosen name says what a group of lines is for, which makes the rest of the program read like a list of steps.
Parameters let a function work on different values
A parameter is a variable in the function's brackets. It gets its value from the argument each time the function is called.
local function greet(name)
print("Hello, " .. name .. "!")
end
greet("Ada")
greet("Sam")This prints Hello, Ada! and then Hello, Sam!. In the first call the parameter name refers to "Ada"; in the second, to "Sam". A function can have several parameters, separated by commas. The arguments are matched to them in order.
return hands a value back
greet shows something on the screen. Many functions should instead work something out and hand the answer back to the line that called them, the way tonumber hands back a number. The statement return does that.
local function area(width, height)
local result = width * height
return result
end
local floor = area(3, 4)
print(floor)
print(area(2, 5) + 1)This prints 12 and then 11. A call such as area(3, 4) is an expression: when it finishes, the call is replaced by the returned value. So you can store it in a variable, or use it in a calculation, as the last line does.
return sends one value back to the place of the call.Three things to know about return:
- It ends the function at once. It must be the last statement of its block, directly before an
endor anelse. - A function that reaches its
endwithout areturnhands backnil. result,widthandheightexist only while the function runs. The rest of the program cannot see them, and that is good: a function's working variables cannot clash with names elsewhere.
print or return?
They look similar when you try a function out, and they are completely different.
printshows text to the person at the screen. The program itself gets nothing back.returngives a value to the program. Nothing appears on the screen unless some line prints it.
local function double_shown(n)
print(n * 2)
end
local function double_returned(n)
return n * 2
end
local a = double_shown(5)
local b = double_returned(5)
print(a)
print(b)This prints 10, nil and 10. The first 10 is printed by double_shown while it runs; it returns nothing, so a is nil. double_returned prints nothing, and b is 10.
A useful rule: functions that work something out should return it, and leave the decision to print to the code that called them.
Functions can contain everything you know
The body of a function is ordinary code: variables, if chains, loops, calls to other functions. A return inside an if chain gives a different answer on each path:
local function ticket_price(age)
if age < 12 then
return 5
elseif age >= 65 then
return 6
else
return 9
end
end
print(ticket_price(8))
print(ticket_price(30))
print(ticket_price(70) + ticket_price(70))This prints 5, 9 and 12.
A complete program
Here is a whole interactive program that uses every lesson of this unit: output, variables, input and conversion, a decision, a loop, and a function. Read it from the top and say what each part does before you read the explanation.
-- A three-question quiz on the 7 times table.
local function mark(answer, correct)
if answer == correct then
return "Right!"
else
return "Not quite: it is " .. correct .. "."
end
end
print("Three questions on the 7 times table.")
local score = 0
for n = 1, 3 do
io.write("What is 7 x " .. n .. "? ")
local answer = tonumber(io.read("l"))
local verdict = mark(answer, 7 * n)
print(verdict)
if verdict == "Right!" then
score = score + 1
end
end
print("Score: " .. score .. " out of 3")With the answers 7, 15 and 21 the session is:
Three questions on the 7 times table.
What is 7 x 1? 7
Right!
What is 7 x 2? 15
Not quite: it is 14.
What is 7 x 3? 21
Right!
Score: 2 out of 3Paste it into the Lua playground with three answers in the Standard input box and try it.
Notice how the work is divided. mark decides and returns a string; it does not print and does not read input. The loop does the talking: it prompts, reads, prints. Splitting a program this way lets you check the deciding part by itself, by calling mark(15, 14) and looking at what comes back.
Two errors you will meet
Calling a function above its definition.
print(double(4))
local function double(n)
return n * 2
end/usr/bin/lua: solution.lua:1: attempt to call a nil value (global 'double')
stack traceback:
solution.lua:1: in main chunk
[C]: in ?You met this message in the first lesson for a misspelt name. The cause here is order: when line 1 runs, Lua has not yet reached the definition, so the name double still refers to nothing. Move the definition to the top.
Too few arguments.
local function area(width, height)
return width * height
end
print(area(3))/usr/bin/lua: solution.lua:2: attempt to perform arithmetic on a nil value (local 'height')
stack traceback:
solution.lua:2: in local 'area'
solution.lua:5: in main chunk
[C]: in ?Lua does not complain at the call. A parameter with no argument is nil, and the program stops later, inside the function, when line 2 tries to multiply by it. This is where the stack traceback earns its place. Read it from the top: the error happened on line 2, in the function area, which was called from line 5. The line to fix is line 5, the call with a missing argument.
A function that forgets its return causes a similar surprise: the call gives nil, and the error appears on the line that uses the result.
What you can do now, and where to go next
You can define functions with local function, pass arguments to parameters, return values, tell print from return, and read a traceback that passes through a function. With variables, input, decisions and loops, that is enough to write complete console programs, and the capstone exercise asks you for one: a number-guessing game.
When you have finished it, you are ready for the next unit of this course. It starts with values, types and truthiness, and the course goes on to tables, Lua's tool for holding many values at once, then strings and patterns, modules, and more. It moves faster than this unit and assumes exactly what you now know.