引言:
什麼是閉包,閉包等不等於函數,upvalue從何而來,upvalue是指針還是值?
function a()
local p = 10
local function b()
p = p + 1
print("this is func b")
print("upvalue params", p )
end
return b
end
b = a()
b() -- 11
b() -- 12
針對上面的栗子:
- 函數b叫做函數a的內嵌函數(inner function)
- 函數a叫做函數b的外包函數(lexical function)
- 變量p內嵌函數的外部局部變量(external local variable),即upvalue
閉包
閉包是什麼?閉包是否等於函數?
記住下面的公式:
閉包 = 函數 + 環境
PS: 環境主要是指upvalue
c = a(); c, b的函數是一樣的,但是upvalue不同,所以當b執行返回值爲12的時候,c執行還是11.
因此,相同函數 == 同一個閉包
upvalue究竟是值傳遞,還是指針傳遞?
先看一段源碼:
typedef struct UpVal {
CommonHeader;
TValue *v; /*points to stack or to its own value */
union {
TValue value; /* the value(when closed)*/
struct { /* double linked list(when open))*/
struct UpVal *prev;
struct UpVal *next;
}l;
}u;
}
upvalue存在2中狀態: closed and open。
- open:執行環境還未銷燬,此時使用指針引用到相應的變量即可。
- closed:執行環境後已經銷燬,需要把值保存到TValue value中,此時已經不再是指針了。
舉個栗子,還是這段代碼:
function a()
local p = 10
local function b()
p = p + 1
print("upvalue params", p )
end
b()
return b
end
b = a()
b()
分析:
b = a(); 執行該行代碼的時候,a調用b,此時a未被銷燬,p對於b就是open的,此時使用TValue *v保存p的指針。
b(); 執行該行代碼的時候,a已經調用結束,此時p對於b就是closed的,p保存在TValue value中,不再是指針。
PS: 想了解lua對upvalue 的處理邏輯,可以閱讀源碼: lvm.c中closure創建,lfunc.c中 luaF_findupval, luaF_close