命令式编程以使用副作用来使程序运行而闻名。相反,函数式编程以最小化副作用而闻名。[1]
由于我有点偏向数学,后者听起来很棒。那么副作用的论据是什么?它们是否意味着失去控制或接受不确定性?它们是一件好事吗?
命令式编程以使用副作用来使程序运行而闻名。相反,函数式编程以最小化副作用而闻名。[1]
由于我有点偏向数学,后者听起来很棒。那么副作用的论据是什么?它们是否意味着失去控制或接受不确定性?它们是一件好事吗?
偶尔我会在Stack Overflow上看到某些问题,这迫使我花费半小时编辑一个非常糟糕的维基百科文章。现在这篇文章只是适度糟糕。在与您的问题相关的部分中,我写道:
在计算机科学中,如果一个函数或表达式除了产生一个值外,还修改了一些状态或与调用函数或外部世界有可观察交互,那么它被称为具有副作用。例如,函数可能会修改全局变量或静态变量,修改其参数之一,引发异常,向显示器或文件写入数据,读取数据,调用其他具有副作用的函数或发射导弹。在存在副作用的情况下,程序的行为取决于过去的历史记录;也就是说,评估的顺序很重要。由于理解具有效果的程序需要考虑所有可能的历史记录,因此副作用经常使程序更难以理解。
副作用是使程序能够与外部世界(人类、文件系统、网络上的其他计算机)交互的重要手段。但是副作用的使用程度取决于编程范型。命令式编程以无序、放纵的副作用使用而闻名。在函数式编程中,副作用很少使用。像Standard ML和Scheme这样的函数式语言不限制副作用,但程序员通常避免使用它们。函数式语言Haskell通过静态类型系统限制副作用;只有产生IO类型结果的函数才能具有副作用。
副作用是必要的,但应该尽量减少或局限其影响。
其他评论中提到,无副作用编程有时不太直观,但我认为人们所谓的“直观”很大程度上取决于他们的先前经验,而大多数人的经验具有强烈的命令式偏见。由于副作用较少,导致组件之间进行交互的可能性降低,因此人们发现无副作用编程可以减少错误(虽然有时会出现新的/不同类别的错误)。每天都有越来越多的主流工具变得更加函数化,这是因为人们在发现无副作用编程的优势。
几乎没有人提到性能问题,无副作用编程通常比有副作用的编程性能更差,因为计算机是冯·诺伊曼机器,设计用于处理效果(而不是使用 lambda 函数)。现在我们正处于多核革命的中心,这可能会改变游戏规则,因为人们发现他们需要利用内核来提高性能,当你没有副作用时并行化有时很容易实现,而有副作用时则需要像火箭科学家一样去实现。
优点:
缺点:
例如Haskell,一开始看起来非常优雅,但是当你需要开始与外部世界进行交互时,就不那么有趣了。(Haskell使用函数参数将状态移动,并将其隐藏在称为Monad的东西中,这使得你可以以类似命令式的方式编写代码。)
没有副作用,有些事情就无法实现。其中一个例子是I/O,因为在屏幕上显示消息本质上就是一个副作用。这就是为什么函数式编程的目标是最小化副作用而不是完全消除它们。
抛开这一点,通常情况下,最小化副作用与其他目标(如速度或内存效率)相冲突。有时候,已经存在一个概念模型与状态变化的想法很好地契合,与这个现有模型对抗可能会浪费能量和精力。
如果没有副作用,就无法执行I/O操作;因此,您无法创建有用的应用程序。
IRenderer
的依赖仍然是对具体Renderer
的依赖,就通信而言,这涉及到哪些副作用将发生。抽象不会影响将发生哪些副作用。