【lua】理解閉包與upvalue

引言:
什麼是閉包,閉包等不等於函數,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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章