Functions can be defined inside other functions. Such nested functions have access to their enclosing scope(s): as a result, they can capture variables in their environment and keep a reference to them, even if they go out of scope. Such functions are called closures. Consider the following example:
function outer(c) var b = 1 function inner() var a = 2 print(a + b + c) end # Return a closure which captures b and c return inner end # Create two closures var f1 = outer(3) var f2 = outer(5)
inner() is defined inside
outer(), and has access to
outer’s variables (its argument
c and its local variable
b). The variables
f2 instances of the function
inner, but each of them with a different captured environment. In
c is 3, whereas it is
f2 are functions, we can call them like any regular function:
f1() # prints "6" f2() # prints "8"
Closures are a powerful construct which allows us to create functions with internal state. They are commonly used to create generators, i.e. functions which can generate new values every time they are called, depending on their internal state. Here is an example of a closure which generates the Fibonacci sequence. We use it to print the first ten values in the sequence.
function fibonacci() var first = 0 var second = 0 function fib() if first == 0 then first = 1 second = 1 return 0 else var current = first var tmp = second second = first + second first = tmp return current end end return fib end var f = fibonacci() for var i = 1 to 10 do print(f()) end