如何在 Lua 中获得闭包?
假设我有一个名为"test.lua"的文件,其中包含以下行:
--[[ test.lua --]]
local f = function()
print"local function f in test.lua"
end
f_generate = function()
local fun = loadstring(" f()")
-- local env = getfenv(1)
-- set(fun,env)
return fun
end
f_generate()()
--[[ end of test.lua--]]
因为loadstring在全局环境下执行它的操作,所以当我调用f_generate()()时,我会得到一个错误"尝试调用全局变量'f'(一个空值)"
注释掉的代码表明函数环境无法解决这个问题。
因为表是lua中唯一的数据结构,(因为函数环境和其他很多东西都是由表实现的),我认为假设闭包也是由表实现的是合理的,但是如何获得它呢?
原文链接 https://stackoverflow.com/questions/897930
你必须移除 'local' 否则它将被垃圾回收。
--local f = function()
f = function()
print"local function f in test.lua"
end
从提出的问题和提供的示例代码来看,在该语言中有函数和闭包作为第一类值的情况下,我不认为需要使用loadstring()
。我会这样做:
-- test.lua
local f = function()
print"local function f in test.lua"
end
f_generate = function()
local fun = function() return f() end
return fun
end
f_generate()()
-- end of test.lua
如果f_generate有参数,则动机更加清晰:
-- test.lua
local f = function(y)
print("local function f("..y..") in test.lua")
end
f_generate = function(name)
local fun = function() return f(name) end
return fun
end
f_generate("foo")()
f_generate("bar")()
-- end of test.lua
通过loadstring()
显式地进行解析将代码带到了loadstring()
调用的作用域之外。本地变量不会存储在任何环境表中。它们的实现方式与任何其他语言中的实现方式相同:它们的存储由代码生成器分配,并且在编译之外无法访问。当然,调试模块(和API)可以查看它们,但是不推荐在调试器之外使用它们。
保留用于范围外部使用的本地变量的正确方法是作为闭包的真正上值。这就是通过fun = function() return f() end
实现的。这种情况下,值f
被保留为存储在fun
中的函数的上值。请注意,实际上,将其包装为上值是非常有效的。不需要查找名称以查找该值,而且由于我使用了尾调用,因此也不需要额外的堆栈帧。
看吧,你不能把函数/闭包当作表来处理。考虑以下代码:
local table = {
baz = {
blah = "bar"
},
foo = table.baz.blah
}
在这种情况下,你正在执行从更宽的作用域访问较窄作用域中的内容的相当于。这对于函数是不可能的,这意味着如果这是正确的话,那么你可以访问通常无法访问的局部变量。
现在,修复你的代码:
local __cmp__table = {
[">"] = function(a,b) return a>b end,
[">="] = function(a,b) return a>=b end,
["<"] = function(a,b) return a<b end,
["<="] = function(a,b) return a<=b end,
["=="] = function(a,b) return a==b end,
["~="] = function(a,b) return a~=b end,
}
cmp = function(a, op, b)
return __cmp__table[op](a,b)
end
这将允许你使用适当的比较函数在任何两个变量上调用 cmp 。如果我错过了你关于代码的重点,请告诉我!
- 如何在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 模式将字符串(嵌套数组)转换为真正的数组?
我认为您正在混淆两件不同的事情:
记住:范围是词法的,而环境是每个函数认为的“全局空间”。
从文本字符串构造的函数处于不同的词法空间,就像它在不同的文件中一样,因此它有自己的范围,与其他函数分开。
顺便说一下,'debug'接口让您干预函数的局部变量,因此可能有一种方法。 我只是没有感到有必要这样做。