有一些关于Lua中“Closure”的问题。
2011-8-4 13:45:5
收藏:0
阅读:139
评论:3
这是我的代码,我混淆了返回函数(c1,c2)中的局部变量“count”与内存栈,并且它们存储在哪里?
function make_counter()
local count = 0
return function()
count = count + 1
return count
end
end
c1 = make_counter()
c2 = make_counter()
print(c1())--打印->1
print(c1())--打印->2
print(c1())--打印->3
print(c2())--打印->1
print(c2())--打印->2
原文链接 https://stackoverflow.com/questions/6935357
点赞
stackoverflow用户139010
在带有内存堆栈的返回函数 c1,c2
中,它们存储在闭包中!
c1
不是闭包,它是通过make_counter()
返回的函数。闭包没有在任何地方明确声明。它是make_counter()
返回的函数和该函数的“自由变量”的组合。参见 closures @ Wikipedia,特别是 implementation :
闭包通常使用一个特殊的数据结构来实现,该结构包含对函数代码的指针,以及在创建闭包时的函数的词法环境的表示(例如,可用变量及其值的集合)。
2011-08-04 03:57:29
stackoverflow用户1946344
Lua 闭包还可以用来实现基于原型的类和对象。闭包类和对象的行为与普通的 Lua 类有些微小的差别,它们的调用方式也略有不同:
-- 定义闭包类
StarShip = {}
function StarShip.new(x,y,z)
self = {}
local dx, dy, dz
local curx, cury, curz
local engine_warpnew
cur_x = x; cur_y = y; cur_z = z
function setDest(x,y,z)
dx = x; dy=y; dz=z;
end
function setSpeed(warp)
engine_warpnew = warp
end
function self.warp(x,y,z,speed)
print("warping to ",x,y,x," at warp ",speed)
setDest(x,y,z)
setSpeed(speed)
end
function self.currlocation()
return {x=cur_x, y=cur_y, z=cur_z}
end
return self
end
enterprise = StarShip.new(1,3,9)
enterprise.warp(0,0,0,10)
loc = enterprise.currlocation()
print(loc.x, loc.y, loc.z)
将产生如下输出:
warping to 0 0 0 at warp 10 1 3 9
这里我们定义了一个原型对象“StarShip”,它是一个空表。
然后,我们创建一个 StarShip 的构造函数,在“new”方法中。它所做的第一件事是创建一个名叫 self 的闭包表,其中包含对象的方法。闭包中的所有方法(在“function self.”中定义的)都对构造函数可访问的所有值进行了“封闭”或定义。这就是为什么它叫做闭包。当构造函数完成时,它将返回闭包对象“return self”。
关于基于闭包的对象的更多信息,请参见:
2013-01-03 18:09:34
评论区的留言会收到邮件通知哦~
推荐文章
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
- 如何编写 Lua 模式将字符串(嵌套数组)转换为真正的数组?
我不太确定您确切想问什么,但我会尝试解释一下闭包的工作原理。
当您在 Lua 中执行以下操作时:
function() <some Lua code> end
您正在创建一个_值_。值是像数字 1,字符串“string”等东西。
值是_不可变的_。例如,数字1始终是数字1。它永远不能是数字2。您可以将1加到2,但这将给您一个新的数字3。对于字符串也是如此。字符串“string”是一个字符串,将始终是该特定字符串。您可以使用 Lua 函数从字符串中删除所有“g”字符,但这将创建一个_新_字符串“strin”。
函数是_值_,就像数字1和字符串“string”一样。值可以存储在变量中。您可以在多个变量中存储数字1。您可以在多个变量中存储字符串“string”。也适用于所有其他类型的值,包括函数。
函数是值,因此它们是不可变的。但是,函数可以_包含_值;这些值是_不_不可变的。这很像表格。
{}
语法创建一个 Lua 表,这是一个值。这张表与任何其他表格都不同,甚至是其他空表。但是,您可以在表格中放入不同的东西。这不会改变表的唯一值,但它确实会改变存储在该表中的内容。每次执行{}
时,都会得到一个新的唯一表。所以如果你有以下函数:function CreateTable() return {} end
以下是正确的:
tableA = CreateTable() tableB = CreateTable() if(tableA == tableB) then print("You will never see this") else print("Always printed") end
即使
tableA
和tableB
都是空表格(包含相同的东西),它们也是_不同_的表格。它们可能包含相同的内容,但它们是不同的值。函数也是如此。在 Lua 中,函数通常被称为“闭包”,特别是如果函数具有内容。根据变量使用情况,函数的内容将给出。如果函数引用在创建该函数的位置处的范围内的局部变量(记住:语法
function()end
每次调用都会创建一个函数_),则该函数将包含对该局部变量的引用。但是,局部变量会超出范围,而函数的值可能会继续存在(在您的情况下,您会返回它)。因此,函数的对象,闭包,必须包含对该局部变量的引用,从而导致它继续存在,直到闭包本身被丢弃。
值存储在哪里?没关系;只有闭包可以访问它们(尽管有通过 C Lua API 或 Lua Debug API 的方法)。因此,与表不同,您可以获取任何您想要的内容,闭包可以真正隐藏数据。