首页 > 其他分享 >Lua闭包

Lua闭包

时间:2024-09-14 16:23:14浏览次数:13  
标签:闭包 upvalue end 函数 -- Lua local

前提概念

词法定界:当一个函数内嵌套另一个函数的时,内嵌函数可以访问外部函数的局部变量,这种特征叫做词法定界。

第一类值:在Lua中,函数是一个值,它可以存在于变量中、可以作为函数参数,也可以作为返回值return。

upvalue:内嵌函数可以访问外部函数已经创建的局部变量,这些局部变量则称为该内嵌函数的外部局部变量(即upvalue)。

Lua中upvalue存储结构:GC信息、指向原型(Prototype)的指针、若干指向upvalue指针
在这里插入图片描述

一个upvalue有两种状态:open和closed。

当upvalue创建时,是open状态,并且它的指针指向Lua栈中对应的变量。

当Lua关闭了一个upvalue,upvalue指向的值被复制到upvalue结构内部,并且指针也相应进行调整。如图所示:
在这里插入图片描述

定义

闭包(closure)是由一个函数和该函数会访问父函数的外部局部变量(upvalue)组成的实体,主要应用在嵌套函数和匿名函数里。

简单理解,闭包由三部分组成:外部函数+外部函数的upvalue+内部函数(闭包函数)

应用

1、闭包的数据隔离
不同实例上的两个不同闭包,闭包中的upvalue变量各自独立,从而实现数据隔离

function func()
  -- 局部变量 index 保存在函数内部中
  local index = 0
  return function()
    print("index is: ", index)
    index = index + 1
  end
end

-- Test
local f1 = func()
f1() -- index is: 0
f1() -- index is: 1

local f2 = func()
f2() -- index is: 0
f2() -- index is: 1

2、闭包的数据共享
两个闭包共享一份变量upvalue,闭包创建时需要的变量不在堆栈上,引用的是更外部函数的局部变量(即upvlaue),变量(对应于示例中的 变量n)是同一个,引用也指向同一个地方,从而实现对共享数据进行访问和修改。

function shareVar(n)
    local function func1()
        print(n)
    end
    
    local function func2()
        n = n + 10
        print(n)
    end
    return func1,func2
end
--创建闭包,f1,f2两个闭包共享同一份upvalue
local f1,f2 = shareVar(1024) 

f1() -- 输出1024
f2() -- 输出1034
f1() -- 输出1034
f2() -- 输出1044

3、利用闭包实现简单的迭代器

迭代器只是一个生成器,本身不带循环。需要在循环里面去调用它。

--- 利用闭包实现iterator,iterator是一个工厂,每次调用都会产生一个新的闭包,该闭包内部包括了upvalue(t,i,n)
--- 因此每调用一次该函数都会产生闭包,那么该闭包就会根据记录上一次的状态,以及返回table中的下一个元素
function iterator(t)
    local i = 0
    local n = #t
    return function()
        i = i + 1
        if i <= n then
            return t[i]
        end
    end
end

testTable = {1,2,3,"a","b"}

-- while中使用迭代器
iter1 = iterator(testTable) --调用迭代器产生一个闭包
while true do
    local element = iter1()
    if nil == element then
        break;
    end
    print(element)
end

-- for中使用迭代器
for element in iterator(testTable) do --- 这里的iterator()工厂函数只会被调用一次产生一个闭包函数,后面的每一次迭代都是用该闭包函数,而不是工厂函数
    print(element)
end

4、创建安全的运行环境(沙盒)

如,通过使用闭包重定义函数 io.open 来限制一个程序能够访问的文件

do
    local oldOpen = io.open
    local accessOk = function(filename, mode)
      --<权限访问检查>
    end
    io.open = function (filename, mode)
        if accessOk(filename, mode) then
          return oldOpen(filename, mode)
        else
          return nil, "access denied"
        end
    end
end

参考资料

【Unity游戏开发】浅谈Lua和C#中的闭包

lua深入理解闭包

标签:闭包,upvalue,end,函数,--,Lua,local
From: https://blog.csdn.net/z2014z/article/details/142106947

相关文章

  • 面试-JS基础知识-作用域和闭包
    问题this的不同应用场景手写bind函数实际开发中闭包的应用场景,举例说明创建10个<a>标签,点击的时候弹出来对应的序号作用域:某个变量的合法使用范围全局函数块级**自由变量上面图的最里面的红框————aa1a2都是自由变量,因为都没有被定义。会一层一层往上找。......
  • 资产定位 | 合宙Air201模组LuatOS快速入门01-hello world
    合宙的Air201模组,功耗低,品质稳定,购买样品也方便,且资料全开放。问题是:用合宙的Air201模组,直接开发OpenCPU的应用,够方便吗?可以不用熟悉繁琐的环境搭建吗?可以不用关注繁琐的编译选项吗?可以不用关心繁琐的C语言陷阱吗?可以用寥寥几行代码,就完成模组对外设的控制,和服务器的......
  • Google Aviator Evaluator 使用入门(一)
    Aviator Evaluator 使用入门(一)https://www.yuque.com/boyan-avfmj/aviatorscript/tvahat一、什么是规则引擎定义:规则引擎是一种软件系统,用于执行基于规则的推理。它将业务规则与事实数据相结合,得出结论。组成:规则引擎通常由规则存储库、推理引擎、工作内存 3个部分......
  • 经典 JS 闭包面试题
    functionfun(n,o){ console.log(o) return{  fun:function(m){   returnfun(m,n);  } };}vara=fun(0);a.fun(1);a.fun(2);a.fun(3);//undefined,?,?,?varb=fun(0).fun(1).fun(2).fun(3);//undefined,?,?,?varc=fun(0).fun(1)......
  • 【PHP编程】PHP闭包函数及函数回调的实现方式
    https://mp.weixin.qq.com/s/ji6hofCun7w7ErRvLuAiuA原创PHP星编程经验共享2023年10月19日08:01广东1.匿名函数在了解回调函数之前我们来了解一下什么是匿名函数?顾名思义,匿名函数就是一个没有确定函数名的函数,PHP将匿名函数和闭包视作相同的概念,所以匿名函数在PHP中......
  • 面试-JS基础知识-作用域和闭包、this
    函数作为返回值functioncreate(){consta=100returnfunction(){console.log(a)//a在这里是自由变量,向上寻找}}constfn=create()consta=200fn()//100函数作为参数functionprint(fn){consta=13fn()}consta=100functionfn(......
  • nginx+lua配置
    nginx中可以配置`--lua校验配置location^~/lua/{default_type'text/html';access_by_lua_file/usr/local/nginx/conf/access.lua;}--重定向配置location^~/toRedirect/{proxy_passhttp://目标ip:目标端口/;proxy_set_headerHost$host;proxy_set_headerX-Re......
  • 使用js闭包实现可取消的axios请求
    在平常开发中,经常会遇到重复请求的情况,也许是因为网络问题,也许是因为接口问题等等,传统做法是客户端采用防抖来限制用户发送接口的频率,一般出个loading转圈圈的形式,但是很少使用取消请求的做法,现在我来记录一下,如何采用闭包来封装一个可取消请求的函数,首先需要了解的是1.闭包2.......
  • nginx安装Lua
    nginx安装lua支持步骤1、下载相关安装包(luajit、ngx_devel_kit、lua-nginx-module)wgethttps://github.com/LuaJIT/LuaJIT/archive/v2.0.4.tar.gzwgethttps://github.com/openresty/luajit2/archive/refs/tags/v2.1-20240626.tar.gzwgethttps://github.com/simpl/ngx_devel_......
  • A COMPREHENSIVE SURVEY ON EVALUATING LARGE LANGUAGE MODEL APPLICATIONS IN THE ME
    本文是LLM系列文章,针对《ACOMPREHENSIVESURVEYONEVALUATINGLARGELANGUAGEMODELAPPLICATIONSINTHEMEDICALINDUSTRY》的翻译。关于评估医疗行业中大型语言模型应用程序的综合调查摘要1引言和背景2综述的分类和结构3医学领域LLM应用评估的现状4挑战......