【问题标题】:Translating a declarative DSL into nested function calls将声明性 DSL 转换为嵌套函数调用
【发布时间】: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


【解决方案1】:

我认为您可以让 python 跟踪函数调用和参数,而不是自己使用堆栈进行。

假设您有一个 YAML 解析树,其中每个节点代表一个函数调用,并且该节点的每个子节点都是一个参数(这也是一个函数调用,因此它可能有自己的参数)。

然后定义函数evaluate,对这棵树的一个节点求值,如下(伪代码):

def evaluate(node):
    # evaluate parameters of the call
    params = []
    for child in node:
        params.append(evaluate(child))

    # now make the call to whatever function this node represents,
    # passing the parameters
    return node.function.call(*params)

最后,调用 evaluate 传递 YAML 树的根作为参数,您应该会得到所需的行为。


一个略有不同的评估应用结构

def evaluate(node):
    # evaluate parameters of the call
    params = [ evaluate(child) for child in node ]

    # apply whatever function this node represents
    return node.function.call(*params)

【讨论】:

  • 为什么是的,那可能就可以了。我不知道为什么这很难想象。
  • “为什么这很难想象”。另一个为什么 DSL 没有多大帮助的例子。 Python 很容易可视化。坚持简单。
  • 我非常确信您对 DSL 的看法不高,我真心希望您永远都不需要用到 DSL。我只想说我希望我的自行车棚被漆成蓝色,我现在要去油漆店了。
  • 很难,零价值,但仍然很重要。有趣的。顺便说一句,这正是 Python 进行表达式评估的方式。
  • 你自相矛盾。它的价值为零,但我刚刚了解了 Python 是如何进行表达式评估的。你的意思是告诉我,通过应用程序学习计算机科学的基本概念是零价值的,还是说在 30 年的编程经验中,你从未构建过类似编译器的任何东西,或者从未在构建中发现任何价值?拜托,感谢您抽出宝贵的时间来尝试和帮助,但我正在尝试在这里学习。关于 DSL,我可能会得出类似的结论,但我需要就此事得出自己的结论。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 2021-09-16
相关资源
最近更新 更多