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的一些特性,对其理解也比较浅显,仍然处于应用阶段。因此其中难免出现各种错误,望指正。

  

时间: 2024-12-22 12:33:07

lua闭包浅析及项目应用的相关文章

javascript闭包浅析

何为闭包; 闭包跟作用域相关的,ECMAScript 允许使用内部函数,即函数定义和函数表达式位于另一个函数的函数体内.内部函数可以访问它们所在的外部函数中声明的所有局部变量.参数和声明的其他内部函数.当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包. 确实有点晕看个例子吧 <!doctype html><html lang="en"><head> <meta charset="UTF-8"> &

浅析在项目开发(使用Delegate回调时)如何正确使用ARC

ARC(自动引用计数)是2011年伴随iOS5来的一项技术.简单来说就是通过LLVM3.0编译器帮助程序处理“一大部分”OC中的内存管理.为什么是“一大部分”,这个等会儿解释. 一直以来内存管理这个话题都是初学iOS开发,初学OC语言必须要面对的知识点,也是大家容易出错的地方.对象释放后调用会造成crash.不释放的对象会造成内存泄漏这些问题困扰着初学者.ARC的到来按理说应该是福音,不需要自己管理内存了嘛,多简单.但是随之而来的两个问题:1,我发现周围有些拥有2-5年开发经验的“半老手”(要谦

LUA闭包概念演示

闭包的一个重要场景,形成一个自治的环境, 让操作可以封闭运行, 即函数运行时有状态的,可以从闭包创建时候的环境独立开来. 例如下面的lua闭包, genFilter 其入参parmIn是 函数的内部变量, 当genFilter被调用时候, 产生的filter闭包,由于使用了 parmIn, 而使得parmIn成为闭包的环境存在. 跟实际入参的 dtype 分离, 其改变不影响闭包变量. local dtype = 2; local function genFilter (parmIn) loca

java翻译lua+c+openssl签名项目

原来项目中用openresty nginx+lua实现server,lua调用c动态链接库,来使用openss做签名,并生成130字节(128签名+2位自定义字节)长度的文件. nginx: location /get/key { content_by_lua_file '/data/www/sign.lua'; } sign.lua local ffi = require "ffi" --动态链接gen_sig_ex_x.c,load("")名字规则,lib***

lua闭包的理解函数与表的几种表达方法

最近工作不是很忙,所以就自学了一些lua的知识,但是才看了两个多小时就遇见了一个问题——闭包.好吧,我是看见它第一眼的时候以为是和close之类有关的巴拉巴拉....(原谅我的无知)!但是越往下看越迷茫,所以就网上看了好多大师写的东西学习学习,特此记录一下,以便日后看到不会.....被人鄙视 在lua中函数也是变量,可以存储在表中,也可以是函数的参数,或是返回值,其实是个lua 的闭包大概可以理解成这个样子 闭包(函数名){功能抽象, upvalue, env},功能抽象就是函数体了, upva

Javascript 闭包浅析(一)

闭包 对于Javascript程序员来说,闭包(closure)是一个难懂又必须征服的概念.闭包的形成与变量的生存周期密切相关. 变量的作用域变量的作用域,指变量的有效范围.我们最常谈到的是在函数中声明的变量作用域.当在函数中声明一个变量的时候,如果该变量前面没有带上关键在var,这个变量就会成为全局变量,这当然是一种容易造成命名冲突的做法.(ES5严格模式下报错)另一种情况是用var关键字在函数中声明变量,这时候的变量既是局部变量,只有在该函数内部才能访问到这个变量,在函数外面是访问不到的.在

lua 闭包

--匿名函数使用upvalue i保存他的计数, 闭包是一个函数加上它可以正确访问的upvalues function newCounter() local i = 0 return function() i = i + 1 return i end end c1 = newCounter() print(c1()) print(c1())

lua闭包

function MakeCounter() local t = 0 return function() t = t + 1 return t end end local func = MakeCounter() for i = 0,10 do print(func()) end local func2 = MakeCounter() for i = 0,10 do print(func2()) end >lua -e "io.stdout:setvbuf 'no'" "

浅析vue项目中的观察者模式

一.什么是观察者模式 定义 "观察者模式是软件设计模式的一种.在此种模式中,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态改变时主动发出通知.这通常透过呼叫各观察者所提供的方法来实现.此种模式通常被用来实时事件处理系统." -------------Wikipedia 作用 当抽象个体有两个互相依赖的层面时.封装这些层面在单独的对象内将可允许程序员单独地去变更与重复使用这些对象,而不会产生两者之间交互的问题. 当其中一个对象的变更会影响其他对象,却又不知道多少对象必须被同