从某种意义上说,任何命令式代码都可以通过使每个操作接收并传递“世界状态”参数来转换为纯函数形式。
然而,假设您有一些几乎是纯函数形式的代码,除了深层隐藏多层函数调用之外,还有一些修改全局或至少广泛访问状态的命令操作,例如:调用一个随机数生成器,更新一个计数器,打印一些调试信息,并且你希望在算法上将它转换为纯函数形式,只需要进行最少的更改。
有没有一种方法可以做到这一点,而基本上没有把整个程序内外?
答案 0 :(得分:1)
从技术上讲,这并不是那么难。
如果您只想避免修改全局状态,例如,使代码重入,那么对于任何读取X的副作用函数F,写入全局变量Y, 并返回Z,将其转换为F',读取X,修改包含传递给它的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中表示的程序转换为功能程序,因为它更容易转换/优化。他们仍然担心全球存储。