關於lua的閉包(Closure)和Upvalue

關於lua的閉包(Closure)和Upvalue

upvalue:嵌套函數的外部函數的局部變量

function func(a) <== 這個函數返回值是一個函數
  return function ()
    a = a + 1    <== 這裏可以訪問外部函數func的局部變量a,這個變量a就是upvalue
    return a 
  end
end



func返回一個匿名函數,可用變量接取之。該匿名函數有一個upvalue a(有點像C函數的static變量),初值爲首次調用func時的參數

閉包:一個匿名函數加上其可訪問的upvalue
c = func(1) <== c現在指向一個擁有upvalue a = 1的匿名函數,c也被稱作一個閉包
c()          <== 返回2
c()          <== 返回3
c2 = func(1) <== c2現在指向另外一個擁有upvalue a = 1的匿名函數,c2也被稱作一個閉包
c2()         <== 返回2

下面是示例代碼:

int generatecclosure(lua_State *L)        /* 閉包產生器 */
{
    lua_pushnumber(L, 0);             /* 壓入第一個upvalue */ 
    lua_pushnumber(L, 0);             /* 壓入第二個upvalue */
    lua_pushcclosure(L, cclosure, 2); /* 壓入閉包的同時也把upvalue置入該閉包的upvalue表 */
    return 1;                         /* 返回閉包 */
}



int cclosure(lua_State *L)
{
    double upval1, upval2;
    upval1 = lua_tonumber(L, lua_upvalueindex(1)); /* 注意upvalue索引1,2是閉包依賴的,不會和其他的閉包中的索引衝突 */
    upval2 = lua_tonumber(L, lua_upvalueindex(2));
    upval1++; upval2++;    
    lua_pushnumber(L, upval1); lua_replace(L, lua_upvalueindex(1));/* 更新upvalue1 */
    lua_pushnumber(L, upval2); lua_replace(L, lua_upvalueindex(2));/* 更新upvalue2 */
    lua_pushnumber(L, upval1 + upval2);
    return 1;
}



int generatecclosure2(lua_State *L)        
{
    lua_pushnumber(L, 10);             
    lua_pushnumber(L, 10);             
    lua_pushcclosure(L, cclosure2, 2); 
    return 1;                          
}



int cclosure2(lua_State *L)
{
    double upval1, upval2;
    upval1 = lua_tonumber(L, lua_upvalueindex(1));
    upval2 = lua_tonumber(L, lua_upvalueindex(2));
    upval1++; upval2++;
    lua_pushnumber(L, upval1); lua_replace(L, lua_upvalueindex(1));
    lua_pushnumber(L, upval2); lua_replace(L, lua_upvalueindex(2));
    lua_pushnumber(L, upval1 + upval2);
    return 1;
}

然後向lua虛擬機註冊一下全局函數:


lua_register(L, "generatecclosure", generatecclosure);
lua_register(L, "generatecclosure2", generatecclosure2);

最後執行main.lua:


c = generatecclosure()
c2 = generatecclosure2()
print(c()) -- 2
print(c()) -- 4
print(c2()) -- 22
print(c2()) -- 24


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