【发布时间】:2011-09-08 21:48:34
【问题描述】:
我有一个 python 库,它从nested function calls 构建特殊的迭代器(行为树)。虽然 API 具有相当不错且轻量级的语法(由于它是 python),但它确实可以使用声明性 DSL。
这是我所设想的粗略草图:
DSL(使用 YAML):
tree:
- sequence:
- do_action1
- do_action2
- select:
- do_action3
- sequence:
- do_action4
- do_action5
- do_action6
将导致以下嵌套函数调用:
visit(
sequence(
do_action1(),
do_action2(),
select(
do_action3(),
sequence(
do_action4(),
do_action5(),
),
do_action6(),
)
)
)
我无法准确地想象如何做到这一点。因为 DSL 必须表示一棵树,所以简单的深度优先遍历似乎是合适的。但是为了构建嵌套的函数调用,我必须以某种方式将其翻过来。它可能涉及一些巧妙的中间堆栈或类似的东西,但我不能完全掌握它。执行此转换的正确方法是什么?
【问题讨论】:
-
“它真的可以使用声明性 DSL”吗?真的吗?你的 Python 代码比你的 DSL 可读性更多。 DSL 有什么帮助?
-
在这个非常简单的示例中,括号特别困扰我。在更复杂的树中,尤其是在涉及关键字 args 时,要求子 (
*args) 出现在选项 (**kwargs) 之前会严重降低可读性。 link to the real-life example 证明了这一点——parallel节点的policy参数很容易被忽略。 -
如果“现实生活中的示例”确实显示了问题,那么也许您应该在此处包含类似的内容。 DSL 是一个有吸引力的麻烦。我还没有看到一个提供任何价值。如果您有示例,请修正此问题,以说明增加复杂性的一些令人信服的原因。
-
问题不在于 DSL 的优点或缺点。一个更复杂的例子会分散如何将解析树转换为特定结构的真正问题。
-
想象一下select,意思是“do_one_of”,写的python实际上调用了所有的孩子,然后返回一个结果。您实际上可能意味着只执行其中一项操作。在这种情况下,python 变得比 DSL 更丑(IMO)。
标签: python parsing dsl behavior-tree