当前位置: 首页 > news >正文

lua闭包浅析及项目应用

 lua函数与闭包:

  原文地址:http://www.doc88.com/p-6681238341344.html

  近日查阅关于lua的一些资料,找到了我能理解的关于lua函数与闭包的解析,我觉得这个程度是我目前所能理解的,特此记录并分享。

  1.

     Lua的函数是一种“第一类值”,即它可以存储在变量或table里,也可以作为实参或“高阶函数”传递给其他函数调用,或作为其它函数的返回值,Lua中的函数的这种特性,使它成为一种灵活,极具弹性的数据类型,同时,也让它延续哼出一些特殊的功能强大的语言机制:闭包。Lua中的函数是带有词法作用域的第一类值,也可以说是函数变量的作用域,即函数的变量有一定的作用范围,变量只能在此范围内可见或被访问。

  例如下面的代码段:

  function count()

    local uv = 0

    local function retfun()

      uv = uv + 1

      print(uv)

    end

    return retfun

  end

  函数retfun定义在函数count中,也可以把函数retfun看作是函数count的内嵌函数,而函数count视为函数的retfun的外包函数。内嵌函数能访问外包函数已经创建的所有局部变量,这种特性就是上文所提到的词法作用域,而这些局部变量(如 uv),则成为该内嵌函数的外部局部变量或upvalue。而当我们执行函数count时有如下结果。

  c1 = count()

  c1()   -- 1

  c2()   -- 2

  对于函数count里的局部变量uv,当执行完"c1 = count()"后, 他的生命周期本该结束,但是因为他已经成为了内嵌函数retfun的upvalue,返回的内嵌函数retfun以upvalue的方式把uv的值保存起来,因此可以正确地把值打印出来。这种局部变量在函数返回后会继续存在,并且返回的函数可以正常调用那个局部变量,独立执行其逻辑操作的现象,在Lua中称之为闭包(closure).闭包是个独立存在的个体,我们在将函数count值赋值给变量c2,

  c2 = count()

  c2() -- 1

  c2() -- 2

  c1和c2都是相同的函数体,但是输出的值却不一样。这是因为闭包是由相应函数原型的引用和upvalue组成。当调用函数造成upvalue值改变时,这只会改变与其对应闭包的upvalue值,不会影响到其他闭包里的upvalue值,从而保持了闭包个体的完整性。闭包在上下文环境中提供很有用的功能:可以作为高级函数的参数;作为函数嵌套的函数;也可以用在回调函数中等。

2. 应用

  之前提到,目前项目用的是skynet,在推送消息的时候需要为每个消息提供一个session值。了解skynet的同学都知道逻辑大部分是写在agent中的但是多个人开发过程中,我们将不同的功能在逻辑上做了划分,例如邮件系统,专门有个emailmgr的脚本来实现,但是实际上还是属于agent的这样主脚本agent中的主动推送函数要传递到各个"分脚本"中。我们希望让整个agent维护一个session,也就是无论哪个模块调用推送函数,都是对同一个session加一操作。这样的一个很自然的想法是在用户登录agent的时候,创建一个session,初始值为1,然后每次推送后都要对session加一。但是这样的话问题就出现了,session若定义成个local number值,那么在传递的时候实际上是传值调用的,也就是各个脚本不会改变agent中的session值。于是便想到了用一个闭包解决此问题。用的函数和例子几乎一样,在agent初始化变量的时候创建闭包,然后各个模块引用此闭包,那么这样就可以直接对该闭包的同一个upvalue进行操作,即可实现所有模块推送时公用此session(upvalue)。

  目前游戏功能模块逻辑还没全部完成,也没多少时间分析lua的一些特性,对其理解也比较浅显,仍然处于应用阶段。因此其中难免出现各种错误,望指正。

 

  

转载于:https://www.cnblogs.com/newbeeyu/p/5451394.html

相关文章:

  • 【跃迁之路】【735天】程序员高效学习方法论探索系列(实验阶段492-2019.2.25)...
  • 验证信息
  • centos6.5环境基于corosync+cman+rgmanager实现RHCS及iscsi+gfs2+clvm的文件系统集群
  • 三步学会用spring开发OSGI——(第二步:工程篇)
  • 个推基于Consul的配置管理
  • Android精品开源整理
  • ECS应用管理最佳实践
  • 大数据分析专题:利用向外扩展技术深入挖掘商业价值(1)
  • Apache搭建简单的图片访问服务器
  • Bootloader之uBoot简介
  • 分布式熔断降级平台aegis
  • 建议
  • dubbo分布式事务
  • HDOJ(HDU) 2178 猜数字(题意有点难理解、、、)
  • Grafana 6.0正式发布!新增查询工作流,全新独立Gauge面板
  • 【node学习】协程
  • JDK 6和JDK 7中的substring()方法
  • Js基础知识(四) - js运行原理与机制
  • seaborn 安装成功 + ImportError: DLL load failed: 找不到指定的模块 问题解决
  • Tornado学习笔记(1)
  • WePY 在小程序性能调优上做出的探究
  • windows下如何用phpstorm同步测试服务器
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 关于使用markdown的方法(引自CSDN教程)
  • 力扣(LeetCode)56
  • 力扣(LeetCode)965
  • 山寨一个 Promise
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 手机端车牌号码键盘的vue组件
  • 微信公众号开发小记——5.python微信红包
  • 原生Ajax
  • 转载:[译] 内容加速黑科技趣谈
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • #if #elif #endif
  • $.ajax,axios,fetch三种ajax请求的区别
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (pytorch进阶之路)CLIP模型 实现图像多模态检索任务
  • (二)hibernate配置管理
  • (附源码)springboot助农电商系统 毕业设计 081919
  • (七)Java对象在Hibernate持久化层的状态
  • (三)c52学习之旅-点亮LED灯
  • (学习日记)2024.03.12:UCOSIII第十四节:时基列表
  • (译) 函数式 JS #1:简介
  • (转)fock函数详解
  • (转)socket Aio demo
  • (转)负载均衡,回话保持,cookie
  • ******IT公司面试题汇总+优秀技术博客汇总
  • .[backups@airmail.cc].faust勒索病毒的最新威胁:如何恢复您的数据?
  • .Net 代码性能 - (1)
  • .NET 使用 XPath 来读写 XML 文件
  • .NetCore 如何动态路由
  • .NET连接MongoDB数据库实例教程
  • .NET轻量级ORM组件Dapper葵花宝典
  • .NET中的十进制浮点类型,徐汇区网站设计