1. Function
In Lua, functions are used as "First-Class Value", which means that functions can be stored in variables, can be passed to other functions through parameters, or as return values of functions (analogous to function pointers in C/C++). This feature gives Lua great flexibility.
Lua provides good support for functional programming and can support nested functions.
In addition, Lua can not only call functions written by Lua, but also functions written by C (all Lua's standard libraries are written in C).
Define a function
function hello()
print('hello')
end
The hello function does not receive parameters, and calls: hello(). Although hello does not receive parameters, you can also pass parameters: hello(32)
In addition, if you only pass one parameter, it can be simplified into the call form of functionname arg (note that the value is not OK)
> hello '3'
hello
> hello {}
hello
> hello 3
stdin:1: syntax error near '3'
Also, it does not apply to variable names.
> a = 21
> print a
stdin:1: syntax error near 'a'
In addition, Lua function does not support the default parameters, and it can be solved very conveniently using or (similar to Javascript)
> function f(n)
>> n = n or 0
>> print(n)
>> end
> f()
0
> f(1)
1
Lua supports returning multiple values, which is very similar to Python in form:
> function f()
>> return 1,2,3
>> end
> a,b,c = f()
> print(a .. b .. c)
123
The return value of the function call can be used in the table:
> t = {f()}
> print(t[1], t[2], t[3])
1 2 3
It can be seen that the three values returned by f() are called the three elements of the table, but this is not always the case:
> t = {f(), 4}
> print(t[1], t[2], t[3])
1 4 nil
This time, the 1, 2, 3 returned by f() only has 1 elements called table;
> t = {f(), f()}
> print(t[1], t[2], t[3], t[4], t[5])
1 1 2 3 nil
In short: Only the last item will use all return values in full (if it is a function call).
For functions without return values, you can use (f()) to force return a value (nil)
> function g()
>> end
> print(g())
> print((g()))
nil
In fact, a call in the form of (f()) returns one and only returns one value
> print((f()))
1
> print(f())
1 2 3
2. Variable length parameters
Lua supports programming parameters and is easy to use (with the help of table and multiple assignments)
> function f(...)
for k,v in ipairs({...}) do
print(k,v)
end
end
> f(2,3,3)
1 2
2 3
3 3
Using multiple assignments
> function sum3(...)
>> a,b,c = ...
>> a = a or 0
>> b = b or 0
>> c = c or 0
>> return a + b +c
>> end
> =sum3(1,2,3,4)
6
> return sum3(1,2)
3
Usually, when traversing variable-length parameters, only {…} is needed, but variable-length parameters may contain some nil; then you can use the select function to access variable-length parameters: select('#', ...) or select(n, ...)
select('#', ...) returns the length of the variable parameter, select(n, ...) is used to access the parameters from n to select('#', ...)
> =select('#', 1,2,3)
3
> return select('#', 1,2, nil,3)
4
> =select(3, 1,2, nil,3)
nil 3
> =select(2, 1,2, nil,3)
2 nil 3
Note: Lua5.0 does not provide... expressions, but use an implicit local table variable arg to receive all variable length parameters, indicating the number of parameters;
3. Functional programming
The function can be assigned a First-Class Value to a variable, and the latter is used to call it.
> a = function() print 'hello' end
> a()
hello
> b = a
> b()
hello
Anonymous functions
> g = function() return function() print 'hello' end end
> g()()
hello
Function g returns an anonymous function;
Closures are an important feature of functional programming, and Lua also supports them.
> g = function(a) return function() print('hello'.. a); a = a + 1 end end
> f = g(3)
> f()
hello3
> f()
hello4
4. Local functions
Local functions can be understood as functions that are valid in the current scope. You can use local variables to refer to a function:
> do
>> local lf = function() print 'hello' end
>> lf()
>> end
hello
> lf()
stdin:1: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
It should be noted that the processing of recursive functions
> do
local lf = function(n)
if n <= 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
stdin:8: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:8: in function 'lf'
stdin:9: in main chunk
[C]: in ?
Instead, you should first declare local lf, and perform assignment
do
local lf;
lf = function(n)
if n <= 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
hello
hello
Lua supports a definition form of local function(…) … end:
> do
local function lf(n)
if n <= 0 then
return
end
print 'hello'
n = n -1
lf(n)
end
lf(3)
end
hello
hello
hello
> lf(3)
stdin:1: attempt to call global 'lf' (a nil value)
stack traceback:
stdin:1: in main chunk
[C]: in ?
5. Tail call
The so-called tail call means that one function returns the return value of another function:
function f()
…
return g()
end
Because after calling g(), no code is executed in f(), there is no need to retain the call information of f(); Lua has made such optimization, which is called "tail call elimination". After g() returns, the control point returns directly to the place where f() is called.
This optimization is very beneficial for tail recursion. Usually recursion means the continuous growth of the caller, which may even cause stack overflow; while tail recursion provides optimization conditions, and the compiler can optimize the caller.
The following recursive function does not use tail recursion, and the parameters are large numbers, stack overflows:
> function f(n)
>> if n <= 0 then
>> return 0
>> end
>> a = f(n-1)
>> return n * a
>> end
> f(10000000000)
stdin:5: stack overflow
stack traceback:
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
...
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:5: in function 'f'
stdin:1: in main chunk
[C]: in ?
Optimized to tail recursion
function f(n, now)
if n <= 0 then
return now
end
return f(n-1, now*n)
end
f(10000000000, 1)
If you run for a long time, there will be no stack overflow;