这段来自awesome wm的 Lua 代码是做什么用的?
看一下这段代码:
local urgent = {}
local capi =
{
client = client,
}
local client
do
client = setmetatable({}, {
__index = function(_, k)
client = require("awful.client")
return client[k]
end,
__newindex = error -- 以防万一
})
end
我对它的理解有些困难。它来自于awesome-wm项目。以下是我理解困难的部分:
- 在声明
capi时使用了client = client
2.在do-end内使用的setmetatable内容
@Nifim的回答非常优秀。我只是想在适当的历史背景下添加更多的内容来解释为什么这段代码存在。在Lua5.2之前,模块系统是不同的。Lua核心库中定义了一个魔术的module()函数。当您创建模块时,您必须先创建所有全局变量的本地版本,然后再调用module(),否则它将在自己的全局环境中运行。"capi"代表"Core API"或"C (语言) API",具体取决于天气。如果Awesome是用我们现在所拥有的所有知识编写的,就不会有一个公共的"C语言"API,它们总是隐藏在私有部分以增加灵活性。现在,设置"c.my_own_property"需要在capi.client和awful.client之间进行几次往返,以适应所有遗留约束。
现在,元表的魔法是一种Lua模式,称为元懒加载。因为"urgent"是"awful.client"的子模块,所以它不能直接导入"awful.client",否则会导致循环依赖。随着Awesome API不断完善,进行了越来越多的重构,通常引入了一些奇怪的依赖关系来保持某种程度的向后兼容性。在最好的情况下,我们应该忽略所有用户配置,重新设计整个代码以避免这些循环依赖关系。但是,每次我们这样做时,所有使用该API的用户都会在一天早上醒来,发现他们无法登录到计算机。因此,这种解决方法存在以避免此类事件,并换取一些奇怪的代码和维护负担。
- Lua 虚拟机加密load(string.dump(function)) 后执行失败问题如何解决
- 我想创建一个 Nginx 规则,禁止访问
- 如何将两个不同的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 代码?

这定义了文件范围内“capi”的哪一部分是可用的。如果查看“client.lua”文件,则会看到其中定义的“capi”具有客户端、鼠标、屏幕和Awesome。
对于在“capi”表中定义的每个项,都有一个相应的.c文件。这些文件定义对象,例如“客户机”。
urgent.lua可以看到这个对象,很可能是一个全局变量,这就是我们可以设置client = client的第二个客户端引用全局变量的方式。下面是两个文件的示例:
main.lua
bar = “Hello World!” local foo = require('foo') print(foo.bar)foo.lua
local foo = { bar = bar } 返回foomain.lua中的打印函数将导致输出“Hello World!”setmetatable在do-end中的内容通过将
setmetatable包裹在一个do-end块中,代码在受限范围内执行。通常这样做是为了包含块的局部变量,使它们不能在代码执行后持续存在。虽然如此,但这个块的目的并不是如此,因为该块没有局部变量。就我看来,阻止只是为了表明修改的对象是client的局部变量,而不是client的全局变量。
此外,metatable在这里用于防止循环依赖循环,这在类似代码出现在项目中的某些地方的注释中有提到,例如在client.lua中定义本地屏幕的地方。