【发布时间】:2013-12-25 11:28:49
【问题描述】:
我是 lua 新手,我正在尝试创建一个配置 DSL,它允许拥有已经具有默认值的部分。
所以,java 表预定义了很多值
java = {
source = 1.6,
target = 1.6,
directories = {
sources = "src/main/java",
output = "build/clases",
},
}
我有一个实现 __call 的 Config 原型,因此当使用表构造函数作为函数调用时,它只会覆盖默认值。像这样的东西:
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 方法允许将原型递归地应用于表,以便所有表都有一个带有 __call 方法集的元表。
我的问题在于“目录”小节。它是在全局上下文中评估的,因此唯一可行的方法是:
java {
source = 1.5,
java.directories {
sources = "customsrcdir",
}
}
这是没有意义的,因为这和做的一样:
java {
source = 1.5
}
java.directories {
sources = "customsrcdir",
}
我尝试了不同的方法来让所需的 DSL 工作。一个是使用 _ENV 设置自定义全局环境,但后来我意识到该表是在 __call 之前评估的。
我想知道是否有更多 lua 经验的人使用更高级的 table/metatable/_ENV 魔法实现了这样的 DSL。
【问题讨论】:
-
在
directories之后添加=会很痛吗?你不能真的说“这是一个函数调用”(你当然知道f ({...})和f {...}之间的相等性),“但现在不要评估它”。除非你用全局状态或类似的东西做一些疯狂的事情。 -
不确定我是否完全理解您的问题。所以你基本上希望
java.directories { "src/main/java2" }与java.directories = { "src/main/java2" }具有相同的效果? -
好吧,如果我使用 '=' 它会覆盖整个表格和默认值。函数调用的想法是我可以只添加不属于模型一部分的传递、验证和忽略键。
-
那么当您执行
java { directories{"src/main/java2"} }时,您在 DSL 中寻找的语义行为是什么?它应该覆盖该字段还是添加到该字段? -
directories 是一个不好的例子,但是如果目录有子键,我只希望在最初初始化的默认值中提到的每个键都被覆盖。我不确定当您像 {"src/main/java2"} 指定它时使用的密钥是什么。