833

到目前为止,我主要接触 OO 编程,并期待学习一门函数式语言。我的问题是:

  • 你什么时候选择函数式编程而不是面向对象?
  • 函数式编程是更好选择的典型问题定义是什么?
4

4 回答 4

1267

你什么时候选择函数式编程而不是面向对象?

当您预期不同类型的软件演进时:

  • 当您对事物有一组固定的操作时,面向对象的语言是很好的,并且随着代码的发展,您主要是添加新事物。这可以通过添加实现现有方法的新类来完成,而现有类则不作任何处理。

  • 当你有一组固定的 东西时,函数式语言是很好的,并且随着你的代码的发展,你主要是在现有的东西上添加新的操作。这可以通过添加使用现有数据类型进行计算的新函数来完成,而现有函数将被单独保留。

当进化走错路时,你会遇到问题:

  • 向面向对象程序添加新操作可能需要编辑许多类定义以添加新方法。

  • 向函数式程序添加新事物可能需要编辑许多函数定义以添加新案例。

这个问题已经众所周知很多年了;1998 年,Phil Wadler 将其称为“表达问题”。尽管一些研究人员认为表达问题可以通过 mixins 等语言特性来解决,但广泛接受的解决方案尚未成为主流。

函数式编程是更好选择的典型问题定义是什么?

函数式语言擅长以树形处理符号数据。一个最喜欢的例子是编译器,其中源语言和中间语言很少更改(大部分相同的东西),但编译器编写者总是添加新的翻译和代码改进或优化(对事物的新操作)。编译和翻译更普遍地是功能语言的“杀手级应用程序”。

于 2010-01-17T01:47:29.927 回答
187

您不一定必须在这两种范式之间进行选择。您可以使用许多功能概念编写具有 OO 架构的软件。FP 和 OOP 本质上是正交的

以 C# 为例。您可以说它主要是 OOP,但有许多 FP 概念和构造。如果您考虑Linq,则允许 Linq 存在的最重要的构造本质上是函数式的:lambda 表达式

另一个例子,F#。您可以说它主要是 FP,但有许多 OOP 概念和构造可用。你可以定义类、抽象类、接口,处理继承。当它使你的代码更清晰或显着提高性能时,你甚至可以使用可变性。

许多现代语言是多范式的。

推荐读数

由于我在同一条船上(OOP 背景,学习 FP),我建议您阅读一些我非常欣赏的读物:

于 2010-01-16T21:39:21.773 回答
32

面向对象编程提供:

  1. 封装,到
    • 控制内部状态的突变
    • 限制与内部表示的耦合
  2. 子类型化,允许:
    • 兼容类型的替换(多态性)
    • 在类之间共享实现的粗略方法(实现继承)

Haskell 甚至 Scala 中的函数式编程可以允许通过更通用的类型类机制进行替换。不鼓励或禁止可变内部状态。也可以实现内部表示的封装。请参阅Haskell 与 OOP进行很好的比较。

Norman 的断言“向函数式程序添加一种新事物可能需要编辑许多函数定义以添加新案例”。取决于功能代码使用类型类的程度。如果特定抽象数据类型的模式匹配分布在整个代码库中,您确实会遇到这个问题,但这可能是一个糟糕的设计。

已编辑在讨论类型类时删除了对隐式转换的引用。在 Scala 中,类型类是用隐式参数编码的,而不是转换,尽管隐式转换是实现兼容类型替换的另一种方法。

于 2010-01-17T12:07:10.323 回答
25
  1. 如果您处于高度并发的环境中,那么纯函数式编程很有用。缺乏可变状态使得并发几乎是微不足道的。见二郎。

  2. 在多范式语言中,如果可变状态的存在必须是实现细节,您可能希望对某些事物进行功能建模,因此 FP 是问题域的一个很好的模型。例如,请参阅 Python 中的列表推导或D 编程语言中的std.range。这些灵感来自函数式编程。

于 2010-01-16T21:41:00.270 回答