[Lua Study Notes] Lua Advanced - Functions and Closures

Insert image description here


function

Function nesting

function A()
    print("这里是函数A")
	return function ()
        print("返回函数不要起名")
    end
end
B = A()
B()

输出:
这里是函数A
返回函数不要起名

Using function nesting, we can use another function as the return value, but the return function as a value must be assigned to other variables, so it cannot be named (assigned) to other variable names when returning.


Closures

Recommended reading: In-depth Lua: Functions and Closures

In function nesting, we need to come into contact with a concept called closure

This is a closure, which consists of a function and the non-local variables (or upvalues) that the function will access.

function f1(n)
   --函数参数n也是局部变量
   local function f2()
      print(n)   --引用外部函数的局部变量,即upvalue
   end
   return f2
end

a =f1(1) --注意,闭包不传入参数则为nil
a()

When a function is nested within another function, the inner function can access the local variables of the outer function. This feature is called lexical scope. What does it mean?

For example, the input parameter n of f1 above is a formal parameter and a local variable within f1. Now another function f2 is defined inside f1. Obviously f2 needs to access the local variable n within f1. But for n, its lexical domain or scope is only within f1. If it is just simple function nesting, it can be implemented in other languages ​​like this:

void f1(int x){
    
    
	f2(x)
}
void f2(int x){
    
    
	return x
}

But the problem is that x in f1 and x in f2 in the above definition are not the same x, but local variables defined in their scopes.

The closure is more equivalent to a pointer, making f2 directly reference the local variables of f1.

#include <iostream>
using namespace std;
void f2(int *x)
{
    
    
	printf("%d", *x);
}
void f1(int x)
{
    
    
	f2(&x);
}
int main()
{
    
    
	int i = 1;
	f1(i);
	return 0;
}

This is the concept of closure: the inner function innerFunction can access and hold the variables in the scope of its outer function outerFunction. These local variables of the outer function referenced by the inner function are called upvalues. In fact, a general function is a special closure in Lua. The entire function produces a closure similar to the following struct:

// Lua闭包
typedef struct LClosure {
    
    
  ClosureHeader;
  struct Proto *p;    // 函数原型
  UpVal *upvals[1];  /* list of upvalues */   // upvalue列表
} LClosure;
function Create(n)
   local function f1()
      print(n)
   end
   local function f2()
      n = n + 10
   end
   return f1,f2
end
a,b = Create(10)
a() -- 10
b()
a() -- 20
b()
a() -- 30

In the above closure, the n used by the two closures f1 and f2 is the same local variable. Therefore, after f2 increases n, the output value of f1 also changes. They share an upvalues.

Now suppose we want to create an object that only provides limited access interfaces to the outside world, and the data inside the object cannot be modified directly, then we can write like this:

local function new_object()
    local obj = {
    
           -- 这就是要创建的对象
        _data1 = 1,     -- 假设这是内部数据
        _data2 = 2,     -- 这是外部可修改的数据
    }
    return {
    
                -- 这是返回的接口table
        get_data2 = function() return obj._data2 end,
        set_data2 = function(value) obj._data2 = value end,
    }
end

local obj_inteface = new_object()
obj_inteface.set_data2(100)
print(obj_inteface.get_data2())     --> 100

variadic function

function f1( x,...)
    arg={
    
    ...}
    for i=1,#arg do
        print(arg[i])
    end
end

We use... to indicate that the parameter is a variable parameter. It can receive parameters of any length, but when we use it, it is best to use a table to receive this variable parameter. In addition, other fixed input parameters must be placed in front of the variable parameters, so that the function can accept the input parameters first and throw the others to the variable parameters.


function overloading

function A()
	print(123)
end
A()

function A(a)
	print(a)
end
A(1)

输出:
123
1

In Lua, function overloading is very simple, just rewrite the function below the function. In Unity, Lua can implement hot updates, such as fixing some bugs, by overloading functions. For example:
Excerpted from Lua Language: Function Level Overloading

-- hotfix.lua
--- 执行热更新
-- oldmod是旧模块
-- newmod是新模块,这个模块里只会提供要替换的函数,相当于旧模块的一个子集。
function hotfix.run(oldmod, newmod)
    -- 收集旧模块的所有upvalue
    local uvmap = collect_all_upvalue(oldmod)
    for k, v in pairs(newmod) do
        if type(v) == 'function' then
            -- 这里就是先把新函数的upvalue修正,然后直接替换给旧模块
            oldmod[k] = hotfix_func(v, uvmap)
        end
    end
end
return hotfix

Guess you like

Origin blog.csdn.net/milu_ELK/article/details/131935321