局部变量在文件内的闭包中无法访问?
假设我有以下两个 Lua 文件:
在 a.lua 中:
local x = 5
f = dofile'b.lua'
f()
在 b.lua 中:
local fun = function()
print(x)
end
return fun
然后如果我在 shell 中运行 luajit a.lua,它会打印 nil,因为在 b.lua 中定义的函数中看不到 x。预期的打印应该是 5。然而,如果我把所有东西都放在一个文件中,那就是我想要的:
在 aa.lua 中:
local x = 5
local f = function()
print(x)
end
f()
运行 luajit aa.lua 它会打印 5。
那么为什么在第一种情况下无法看到 x?
我同意这种方法有些不直观。
你可能想说,在代码的任何时刻,有一组明确的“可见”变量--有些可能是局部的,有些可能是全局的,但有一些映射关系,解释器可以用来解决任何一种名称。
当你使用dofile加载一个块时,它可以看到当前存在的任何全局变量,但显然它无法看到任何局部变量。我们知道"dofile"不像C/C++的宏包含,后者将为本地变量提供你所描述的确切语法,但你可能合理地期望它的一部分会工作得一样。
最终没有答案,只有“这仅仅是他们指定语言的方式”。唯一令人满意的答案可能是:“否则会导致非显而易见的问题X”或“因为使用情况Y会变慢”。
我认为最好的答案是,如果使用loadfile/dofile时,所有名称都是根据它们被加载的范围动态重新绑定的,那么在将块编译为字节码时,会抑制很多优化等方面的工作。在lua系统中,名称解析的工作方式是“要么它在这个作用域中是本地的,然后它绑定到该(已知的)对象,要么它是在(唯一的)全局表中查找”。该系统非常简单,只有少数几个选项,没有太多的复杂性。
我认为即使运行字节代码也不会跟踪本地变量的名称,它会在块编译后将它们丢弃。如果他们想要在块装载时允许动态名称解析,就必须撤销那种优化。
如果你的问题不是“为什么”,而是“我该如何让它仍然工作”,则你可以在主机脚本中,将任何你想要可见的局部变量放入被调用的脚本的环境中。当你这样做时,你需要将dofile分成几个调用。在Lua 5.1和Lua 5.2中稍有不同。
在Lua 5.1中:
在a.lua中:
local shared = { x = 5 }
temp = loadfile('b.lua')
setfenv(temp, shared)
f = temp()
f()
在Lua 5.2中:
在a.lua中:
local shared = { x = 5 }
temp = loadfile('b.lua', 't', shared)
f = temp()
f()
在a.lua模块中定义的变量x无法从b.lua中看到,因为它被声明为局部变量。局部变量的作用域是它自己的模块。
如果想让x从b.lua中可见,只需要声明它为全局变量。一个变量要么是局部的,要么是全局的。要将一个变量声明为全局变量,只需不将它声明为局部变量即可。
a.lua
x = 5
f = dofile'b.lua'
f()
b.lua
local fun = function()
print(x)
end
return fun
这是有效的。
全局变量存在于全局命名空间中,可以随时通过_G表访问。当Lua无法解析变量时,因为它未在使用它的模块中定义,Lua会在全局命名空间中搜索该变量。总之,也可以将b.lua写成:
local fun = function()
print(_G["x"])
end
return fun
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在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中获取用户配置主目录的跨平台方法
如其名称所示,局部变量仅在代码块中有效。
dofile()从另一个文件中加载代码块。由于这是另一个代码块,第一个代码块中的局部变量x并不会影响它。