来自 awesome wm 的这段 lua 代码有什么作用?
What does this piece of lua code from awesome wm do?
看看这段代码:
local urgent = {}
local capi =
{
client = client,
}
local client
do
client = setmetatable({}, {
__index = function(_, k)
client = require("awful.client")
return client[k]
end,
__newindex = error -- Just to be sure in case anything ever does this
})
end
我无法理解它的作用。它来自 awesome-wm
项目。这些是我难以理解的事情:
client = client
在 capi
的声明中
setmetatable
里面的东西do-end
client = client
in the declaration of capi
这是定义 capi 的哪一部分在此文件的范围内可用,如果您查看 client.lua 文件,您会看到其中定义的 capi
具有客户端、鼠标、屏幕, 太棒了。
对于 capi
table 中定义的每个项目,都有一个对应的 .c 文件。这些文件定义了 client
等对象。 urgent.lua
具有该对象的可见性,可能它是一个全局变量,这就是我们如何设置 client = client
第二个客户端引用全局变量。
以下是 2 个文件的示例:
main.lua
bar = "Hello World!"
local foo = require('foo')
print(foo.bar)
foo.lua
local foo = {
bar = bar
}
return foo
main.lua 中的打印函数将导致 Hello World!
setmetatable
stuff inside do-end
这里通过扭曲 do-end 块中的 setmetatable
代码在受限范围内执行。通常这样做是为了包含块的局部变量,以便它们在代码执行后不会持续存在。
那不是这个块的目的,因为这个块没有局部变量。如我所见,阻塞只是为了表明被修改的对象是client的局部变量而不是客户端的全局变量.
另外这里的metatable是用来防止循环依赖的,在项目中一些类似代码出现的地方有注释提到,比如client.lua
where local screen
已定义。
@Nifim 回答得很好。我只是想添加更多关于 为什么 此代码存在于其适当的历史背景中的上下文。在 Lua 5.2 之前,模块系统不同。在核心 Lua 库中定义了一个神奇的 module()
函数。当你制作一个模块时,你 必须 在调用 module()
之前首先制作所有全局变量的本地版本,否则它会 运行 在它自己的全局环境中。 "capi" 代表 "Core API" 或 "C (language) API" 取决于天气。如果 Awesome 是今天用我们现在拥有的所有知识编写的,就不会有 public "C language" API 并且它们将始终隐藏在私有部分以增加灵活性。现在设置 "c.my_own_property" 在 capi.client 和 awful.client 之间进行几次往返只是为了适应所有遗留约束。
现在,元表魔法是一种称为元延迟加载的 Lua 模式。因为 urgent
是 awful.client
的子模块,所以不能直接导入 awful.client
而不会造成循环依赖。随着时间的推移,随着 Awesome API 的定义变得更好,进行了越来越多的重构,并且它们经常引入奇怪的依赖关系以保持一定程度的向后兼容性。在最好的情况下,我们会忽略所有用户配置并重新设计整个代码以避免这些循环依赖。然而,每次我们这样做时,上述 API 的所有用户都会在一天早上醒来,他们无法再登录到他们的计算机。因此,存在这种解决方法是为了防止 return 中出现此类事件,以解决一些奇怪的代码和维护负担。
看看这段代码:
local urgent = {}
local capi =
{
client = client,
}
local client
do
client = setmetatable({}, {
__index = function(_, k)
client = require("awful.client")
return client[k]
end,
__newindex = error -- Just to be sure in case anything ever does this
})
end
我无法理解它的作用。它来自 awesome-wm
项目。这些是我难以理解的事情:
client = client
在capi
的声明中
setmetatable
里面的东西do-end
client = client
in the declaration ofcapi
这是定义 capi 的哪一部分在此文件的范围内可用,如果您查看 client.lua 文件,您会看到其中定义的 capi
具有客户端、鼠标、屏幕, 太棒了。
对于 capi
table 中定义的每个项目,都有一个对应的 .c 文件。这些文件定义了 client
等对象。 urgent.lua
具有该对象的可见性,可能它是一个全局变量,这就是我们如何设置 client = client
第二个客户端引用全局变量。
以下是 2 个文件的示例:
main.lua
bar = "Hello World!"
local foo = require('foo')
print(foo.bar)
foo.lua
local foo = {
bar = bar
}
return foo
main.lua 中的打印函数将导致 Hello World!
setmetatable
stuff insidedo-end
这里通过扭曲 do-end 块中的 setmetatable
代码在受限范围内执行。通常这样做是为了包含块的局部变量,以便它们在代码执行后不会持续存在。
那不是这个块的目的,因为这个块没有局部变量。如我所见,阻塞只是为了表明被修改的对象是client的局部变量而不是客户端的全局变量.
另外这里的metatable是用来防止循环依赖的,在项目中一些类似代码出现的地方有注释提到,比如client.lua
where local screen
已定义。
@Nifim 回答得很好。我只是想添加更多关于 为什么 此代码存在于其适当的历史背景中的上下文。在 Lua 5.2 之前,模块系统不同。在核心 Lua 库中定义了一个神奇的 module()
函数。当你制作一个模块时,你 必须 在调用 module()
之前首先制作所有全局变量的本地版本,否则它会 运行 在它自己的全局环境中。 "capi" 代表 "Core API" 或 "C (language) API" 取决于天气。如果 Awesome 是今天用我们现在拥有的所有知识编写的,就不会有 public "C language" API 并且它们将始终隐藏在私有部分以增加灵活性。现在设置 "c.my_own_property" 在 capi.client 和 awful.client 之间进行几次往返只是为了适应所有遗留约束。
现在,元表魔法是一种称为元延迟加载的 Lua 模式。因为 urgent
是 awful.client
的子模块,所以不能直接导入 awful.client
而不会造成循环依赖。随着时间的推移,随着 Awesome API 的定义变得更好,进行了越来越多的重构,并且它们经常引入奇怪的依赖关系以保持一定程度的向后兼容性。在最好的情况下,我们会忽略所有用户配置并重新设计整个代码以避免这些循环依赖。然而,每次我们这样做时,上述 API 的所有用户都会在一天早上醒来,他们无法再登录到他们的计算机。因此,存在这种解决方法是为了防止 return 中出现此类事件,以解决一些奇怪的代码和维护负担。