Let's talk about functions and closures. A closure is a function that refers to variables declared outside of itself, but which are not globals.
For this part of the video, I'm going to use a text editor to write my Lua because, in practice, you'll be using a text editor to write your code, and multiline Lua doesn't work as well in the interpreter.
-- In the file fn.lua:
function abc(a, b, c)
print(a, b, c)
return 3
end
I've declared a global function here called abc
.
Syntax for functions always starts with the word function
and
ends with the word end
.
Within the interpreter, I can use the built-in dofile
function
to load and execute this script.
That's what the dofile
function does.
> dofile('fn.lua')
Now I can call abc
with any three values that I like, like this:
> abc(1, 2, 'hi')
1 2 hi
Similar to flexible assignments, Lua function calls accept a flexible
number of parameters.
If I call abc
with a single parameter, then the extra variables
inside the function receive the nil
value.
> abc(1)
1 nil nil
If I call the function with extra values, the extra values are discarded.
> abc(1, 2, 3, 4)
1 2 3
Return values work similarly. I can accept more or fewer values than are actually returned by the function.
> a, b = abc()
nil nil nil
> = a
3
> = b
nil
Now I'm going to define a function that returns 4 values.
-- In the file fn.lua:
function ret4()
return 4, 5, 6, 7
end
When you chain function calls together, the output of one function goes into the input of another, similarly to flexible assignment.
In this example, the extra return value 7 will be discarded.
> dofile('fn.lua')
> abc(ret4())
4 5 6
You can also create anonymous functions. The syntax is the same, except that you leave out the name of the function. Here's an example that returns an empty table:
> g = function () return {} end
> = g()
table: 0x7fdfd170a9f0
And you can create local functions. That means the function, considered as a variable, only has local scope.
> local function hi() print('hi') end
This is useful when you're writing a module and you want to call an internal function that isn't visible outside the scope of the module.
Let's take a look at an example of a closure.
I'm going to define a function called adder
which takes a number called
x
and returns an anonymous function which adds a new number y
and x
.
-- In the file fn.lua:
function adder(x)
return function (y)
return x + y
end
end
I'll load these into Lua:
> dofile('fn.lua')
Now I can make a new variable called add1
which is the return value of
adder(1)
:
> add1 = adder(1)
and add30
which is the return value of adder(30)
:
> add30 = adder(30)
These are different functions, and when I call them with the same input, say 12, I'll get different outputs:
> = add1(12)
13
> = add30(12)
42
The important thing here is that each of these functions has its own
private copy of the variable x
with a different value.
If closures are new to you, this is a basic example
to see the general idea.