最近,我听到很多关于使用功能语言(例如Haskell)的讨论。函数式编程与面向对象的编程之间的优缺点有哪些?
最近,我听到很多关于使用功能语言(例如Haskell)的讨论。函数式编程与面向对象的编程之间的优缺点有哪些?
Answers:
最大的区别是命令式编程与控制流有关,而功能性编程与数据流有关。换句话说,函数式编程仅使用表达式,而命令式编程则同时使用表达式和语句。
例如,在命令式编程中,处理状态时会使用变量和循环,而在函数式编程中,则通过参数传递来处理状态,从而避免了副作用和赋值。
用于计算列表总和的函数的命令式伪代码(总和保存在变量中):
int sumList(List<int> list) {
int sum = 0;
for(int n = 0; n < list.size(); n++) {
sum = sum + list.get(n);
}
return sum;
}
相同功能的功能伪代码(总和作为参数传递):
fun sumList([], sum) = sum
| sumList(v::lst, sum) = sumList(lst, v+sum)
函数式编程基于声明性模型,并且起源于lambda演算。它提供了许多很棒的概念,可以从诸如C ++和C#的命令式语言中借用。
一些示例包括参照透明性,lambda函数,一流函数,惰性和渴望评估以及不变性。
如果没有别的,学习函数式编程对于其中包含的概念很有用。它将改变您进行编程和思考编程的方式。而且我猜想将来函数式编程将和面向对象的编程一样重要。
首先,您可以选择使用诸如Haskell之类的纯函数式语言,也可以使用诸如F#之类的混合语言。
大多数优秀的大学都将涵盖功能编程,如果您要上学,我强烈建议您参加那门课程。
函数式编程与面向对象的编程之间的优缺点有哪些?
面向对象的编程很好,因为它允许您将复杂的问题建模为层次结构,从而可以简化问题。但是,当您开始考虑使用可变对象时进行多线程编程时,这将变得非常困难。在这种情况下,您需要大量使用同步对象,而完善大型应用程序几乎是不可能的。
那就是函数式编程的源头。由于不可变性之类的功能,函数式编程确实简化了多线程程序。当您知道给定输入X到函数将始终输出Y时,几乎可以轻松地并行化某些内容。此外,您知道变量(或函数编程中的值)不能在另一个线程的中间使用中更改。
(此答案是从StackOverflow上的已解决问题的答案改编而成的。)
函数式编程和面向对象的编程之间的最大区别之一是,每个编程人员都擅长于不同类型的软件演进:
当您对事物进行固定的操作时,面向对象的语言是很好的选择,并且随着代码的发展,您主要添加新的事物。这可以通过添加实现现有方法的新类来完成,而现有类则不理会。
当您拥有固定的事物集时,功能语言是很好的选择 ,并且随着代码的发展,您主要在现有事物上添加新的操作。这可以通过添加使用现有数据类型进行计算的新函数来完成,而现有函数则不予考虑。
当进化走错路时,您就会遇到问题:
向面向对象的程序添加新操作可能需要编辑许多类定义以添加新方法。
向功能程序中添加新事物可能需要编辑许多功能定义以添加新案例。
这个问题已经众所周知很多年了。1998年,菲尔·沃德勒(Phil Wadler)将其称为“表达问题”。尽管一些研究人员认为可以使用诸如mixin之类的语言功能来解决表达问题,但尚未得到广泛接受的解决方案成为主流。
没有真正的对。它们可以完全互补。FP语言支持OOP。但是社区在处理模块化方面的方式有所不同。
FP语言的用户倾向于通过数学定律实现模块化。并且更喜欢证明其法律合规的证据。
在命令式OOP中,用户倾向于在测试用例中捕获对象的行为,如果对象已更改,则可以重新运行该对象并以这种方式实现模块化。
这只是一个小方面,但我认为值得一提。
打个比方:
您已收到工作申请书。您填写姓名,联系方式和工作经历。完成后,您将不再有空白的应用程序。
现在想象一下,写之前先用透明的玻璃纸覆盖它。你写你的名字。您添加另一张玻璃纸。您写您的联系信息。玻璃纸。您写下您的工作记录。完成后,您仍然可以使用空白应用程序。您还拥有三张玻璃纸,每张都捕获了单个离散变化的效果。
前者(OOP)接受将事物更改为原位的想法,而后者(FP)则避免。两者都是状态管理范例。两者都可以使用不同的策略来捕获完成求职申请的效果。OOP直接更改启动工具,而FP覆盖之前发生的变化以影响更改的外观。