0

概括

将纯函数拆分为描述算法的被动对象和可以执行这些算法的主动对象有什么优缺点?请注意,由于函数没有副作用,这种情况大大简化了。

细节

我正在编写的代码部分(在 Python 3 中)将在很大程度上遵循函数式编程。

有一些(不可变的)数据。有一些算法。我需要将这些算法应用于数据,并得到结果。

算法可以表示为常规函数,这些函数将使用标准操作进行转换(例如,我可以组合两个函数,然后使用 冻结一些参数functools.partial,然后将结果函数作为参数传递给另一个函数)。出于性能原因,许多较低级别的函数将被记忆。

但是我想到了一个想法,也许我应该将算法表示为被动对象。这样的对象自己将无法执行任何操作。当我准备好执行时,我会将算法对象和它期望的所有输入提供给一个特殊的“计算”对象。这将更好地匹配我对算法的心理模型,但我担心我可能会遗漏这种方法的一些问题。

算法对象可以以多种方式实现;也许甚至可以允许多个实现。假设我的算法是抽象类算法的实例;那么它的子类可以代表:

  • 我将创建的特定领域语言的文本字符串
  • 我将构建的某种执行树
  • 甚至是常规的 Python 函数

我以前从未这样做过,所以我想就这个想法得到一些反馈。除了我的主观感觉它更“自然”之外,它是否提供任何真正的设计优势?它会导致任何问题吗?

4

1 回答 1

1

我不认为该设计提供任何主要的优势或劣势。

假设任何计算对象都可以运行任何算法,那么你的类Algorithm可能会有一个函数,叫做类似的函数execute,知道如何运行算法。命名该函数__call__,现在你的Algorithm类就像一个 Python 可调用对象(包括函数)。

对于您的 DSL 代码字符串:在您的设计下,您会将它们表示为Algorithm覆盖execute运行解释器的子类。在另一种设计下,您只需执行以下操作:

def createDSLAlgorithm(code):
    def coderunner(*args, **kwargs):
        DSLInterpreter().interpret(code, *args, **kwargs)
    return coderunner

与创建函数类似,该函数在调用时将执行指定的表达式树。

当然,我可能会遗漏一些你计划在你的算法设计中加入的东西,而这些东西对于函数来说是不可能的。例如,并非所有Python 函数都具有可变属性。但是由于用户定义的函数可以是闭包,可以具有属性,并且任何对象都可以通过实现“表现得像一个函数” __call__,我怀疑它是同一事物的不同名称。

当然,如果它有助于代码的可读性,选择你自己的名字是一个小优势。如果您的计算对象要询问算法的某些已知属性以帮助决定在计算它们时要做什么,那么将属性附加到“对象”可能比将它们附加到“函数”更自然一些(例如是否要记忆)。

于 2012-09-09T22:06:02.160 回答