【问题标题】:Converting code to pure functional form将代码转换为纯函数形式
【发布时间】:2016-08-24 15:53:10
【问题描述】:

在某种意义上,任何命令式代码都可以通过让每个操作接收和传递“世界状态”参数来转换为纯函数形式。

但是,假设您有一些几乎是纯函数形式的代码,除了深埋了许多函数调用层之外,是一些修改全局或至少广泛访问的状态的命令式操作,例如调用随机数生成器、更新计数器、打印一些调试信息,然后您希望通过算法将其转换为纯函数形式,并且更改最少。

有没有一种方法可以做到这一点,而无需将整个程序彻底翻转?

【问题讨论】:

  • 你的意思是你的程序有副作用?
  • @OliverCharlesworth 是的。只有一小部分代码行有副作用,但它们被深埋了许多层的函数调用,我想自动将其转换为没有副作用的程序,同时尽可能多地保留原始结构。
  • 你的意思是,找到执行副作用的行并删除它们?
  • @Bergi 不,转换必须保留程序的含义。
  • 副作用是程序含义的一部分。举一个例子,在“打印一些调试信息”的情况下,您希望转换的最终结果是什么?

标签: functional-programming automated-refactoring


【解决方案1】:

这在技术上并不难。

如果您只想避免修改全局状态,例如,使代码可重入,那么对于读取 X、写入全局变量 Y 的任何副作用函数 F, 并返回 Z,将其转换为读取 X 的 F',修改包含传递给它的 Y 的结构,并返回 Z。如果 A 调用 B 调用 .. 传递调用 F, F 修改全局 Y,然后 A' 必须构建对包含 Y 的结构的引用并将其传递给 B。现在您的所有函数只修改传递给它们的值;它们对全局状态没有副作用。 (好吧,我们可以争论 A' 做了什么)。

[有人可能会抱怨 F 完成的(文件/屏幕/设备)输出无法处理。好吧,要么你想要对世界产生直接的副作用,要么你不想要。如果不这样做,请将输出的“状态”添加为 Y,然后对其进行修改; A' 可以作为结果返回所需的输出。]

如果你坚持让程序函数式,那么 F 对全局 Y 的任何副作用都已更改为将 Y 传入,复制 Y 同时将其更改为生成 Y',然后是 F'必须返回一对。 F 的调用者必须传入 Y,并在调用站点可访问的所有代码中使用生成的 Y'。

关于复制的问题会让你陷入真正的麻烦:在哪里找到对 Y 进行深度复制的逻辑?如果你找到它,你可能会发现深拷贝会产生巨大的结构,你的存储需求很快就会变得不可能。现在你需要找到一种方法让 Y' 共享 Y 中没有改变的部分。

现在,如果您想在大代码上执行这些任务中的任何一个,您可能不想手动完成;人们不擅长处理这种细节,他们想作弊/重写/...如果你真的想这样做,你想要一个source-to-source program transformation system,它可以机械地应用必要的步骤。

我会注意到标准编译技术将程序转换为所谓的“静态单一分配 (SSA)”形式,该形式将 IR 中表示的尽可能多的程序转换为功能程序,因为它更容易转换/优化。他们仍然担心全局存储。

【讨论】:

    猜你喜欢
    • 2021-08-01
    • 2011-09-30
    • 2011-04-06
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-05
    相关资源
    最近更新 更多