gpt4 book ai didi

lua - 使用 __call 与 lua 创建 DSL,如何实现小节?

转载 作者:行者123 更新时间:2023-12-04 02:37:00 28 4
gpt4 key购买 nike

我是 lua 的新手,我正在尝试创建一个配置 DSL,它允许具有已经具有默认值的部分。

因此,java 表预定义了很多值

java = {
source = 1.6,
target = 1.6,
directories = {
sources = "src/main/java",
output = "build/clases",
},
}

我有一个实现了 __call 的 Config 原型(prototype),这样当作为一个带有表构造函数的函数被调用时,它只会覆盖默认值。像这样的东西:

Config.__call = function(t, props)
for k,v in pairs(props) do
t[k] = v
end
end

这个想法是你可以只调用 dsl 来指定你想要覆盖的内容:

java {
source = 1.5,
directories {
sources = "customsrcdir",
}
}

有一个 Config.new 方法允许递归地将原型(prototype)应用到表中,以便所有表都有一个设置了 __call 方法的元表。

我的问题是“目录”小节。它是在全局范围内评估的,因此唯一可行的方法是:

java {
source = 1.5,
java.directories {
sources = "customsrcdir",
}
}

这是没有意义的,因为这和做是一样的:

java {
source = 1.5
}

java.directories {
sources = "customsrcdir",
}

我尝试了不同的方法来让所需的 DSL 工作。一个是使用 _ENV 设置自定义全局环境,但后来我意识到该表是在 __call 之前评估的。

我想知道是否有更多 lua 经验的人使用更高级的表/元表/_ENV 魔法实现了这样的 DSL。

最佳答案

可以按您的方式调用,但解决方案非常复杂,不值得省略 =。如果您仍然想要表格合并/替换功能,那并不太难。

local function merge(t1, t2)
for k, v in pairs(t2) do
-- Merge tables with tables, unless the replacing table is an array,
-- in which case, the array table overwrites the destination.
if type(t1[k]) == 'table' and type(v) == 'table' and #v == 0 then
merge(t1[k], v)
else
t1[k] = v
end
end
end

local data = {
java = {
source = 1.6,
target = 1.6,
directories = {
sources = "src/main/java",
output = "build/classes",
},
}
}

local dsl = {}
load( [[
java = {
source = 1.5,
directories = {
sources = "customsrcdir",
},
}
]], 'dsl-config', 't', dsl)()

merge(data, dsl)

转储数据将导致:

java = {
directories = {
output = "build/classes",
sources = "customsrcdir"
}
source = 1.5,
target = 1.6
}

关于lua - 使用 __call 与 lua 创建 DSL,如何实现小节?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20772271/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com