将代码转换为纯函数形式

Converting code to pure functional form

从某种意义上说,任何命令式代码都可以通过使每个操作接收并传递一个 'state of the world' 参数来转换为纯函数形式。

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

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

这在技术上并不难。

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

[有人可能会抱怨 (File/Screen/Device) F 完成的输出无法处理。好吧,要么你想要对世界产生直接的副作用,要么你不想。如果你不这样做,将Output的"state"添加为Y,并修改它; A' 可以 return 结果得到想要的输出。]

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

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

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

我会注意到,标准编译技术将程序转换为所谓的 "static single assignment (SSA)" 形式,它将尽可能多的程序(以 IR 表示)转换为功能程序,因为它更容易 transform/optimize.他们仍然担心全局存储。