All*_*ate 9 functional-programming side-effects
我试图了解功能语言的核心概念:
"函数式语言的一个核心概念是函数的结果是由它的输入决定的,只有它的输入决定.没有副作用!"
我的问题是,如果一个函数只在其本地环境中进行更改,并返回结果,它如何与数据库或文件系统交互?根据定义,不会访问实际上是全局变量或全局状态的东西吗?
用于解决或解决此问题的最常见模式是什么?
dfl*_*str 11
仅仅因为函数式语言是功能性的(也许甚至完全像Haskell一样纯粹!),这并不意味着用该语言编写的程序在运行时必须是纯粹的.
例如,在处理副作用时,Haskell的方法可以简单地解释:让整个程序本身是纯粹的(意味着函数总是为相同的参数返回相同的值,并且没有任何副作用),但是让main函数的返回值成为可以运行的动作.
试图用伪代码来解释这个问题,这里有一些命令式,非功能性的语言:
main:
read contents of abc.txt into mystring
write contents of mystring to def.txt
Run Code Online (Sandbox Code Playgroud)
上述main过程就是:描述如何执行一系列操作的一系列步骤.
将其与Haskell等纯功能语言进行比较.在函数式语言中,一切都是表达式,包括主函数.因此可以像这样读取上述程序的等价物:
main = the reading of abc.txt into mystring followed by
the writing of mystring to def.txt
Run Code Online (Sandbox Code Playgroud)
因此,main是一个表达式,在评估时,将返回描述要执行程序的操作的操作.这个动作的实际执行发生在程序员世界之外.这就是它的工作原理; 以下是可以编译和运行的实际Haskell程序:
main = readFile "abc.txt" >>= \ mystring ->
writeFile "def.txt" mystring
Run Code Online (Sandbox Code Playgroud)
a >>= b在这种情况下,可以说是"行动a结果所遵循的a行动b",而运营商的结果是联合行动a和b.上述程序当然不是惯用的Haskell; 可以按如下方式重写它(删除多余的变量):
main = readFile "abc.txt" >>=
writeFile "def.txt"
Run Code Online (Sandbox Code Playgroud)
...或者,使用语法糖和记号:
main = do
mystring <- readFile "abc.txt"
writeFile "def.txt" mystring
Run Code Online (Sandbox Code Playgroud)
所有上述程序不仅相同,而且就编译器而言它们是相同的.
这就是如何将文件,数据库系统和Web服务器编写为纯函数式程序:通过程序对操作值进行线程处理以便将它们组合在一起,最后在main函数中结束.这为程序员提供了对程序的巨大控制,这也是纯函数式编程语言在某些情况下如此吸引人的原因.
处理函数式语言中副作用和杂质的最常见模式是:
例子:
set!varHaskell做了一点作弊 - 它的解决方案是,对于访问文件系统或数据库的函数,该瞬间整个Universe 的状态,包括文件系统/ db的状态,将被传递给该函数. (1)因此,如果你可以在那一瞬间复制整个宇宙的状态,那么你可以从这样一个函数得到两次相同的结果.当然,你不能在那个瞬间复制整个宇宙的状态,因此函数返回不同的值......
但是Haskell的解决方案,恕我直言,并不是最常见的.
(1)不确定这里的具体细节.感谢CAMcCann指出这个比喻被过度使用,可能并不那么准确.