FP 和 OO 正交吗?

发布于 2024-09-27 17:24:57 字数 253 浏览 0 评论 0原文

我一次又一次地听到过这种说法,我正在尝试理解和验证 FP 和 OO 是正交的这一想法。

首先,两个概念正交是什么意思?

FP 尽可能鼓励不变性和纯粹性,而 OO 似乎是为状态和突变而构建的——命令式编程的稍微组织的版本?我意识到对象可以是不可变的,但面向对象对我来说似乎意味着状态/更改。

他们看起来是对立的。这如何影响它们的正交性?

像 Scala 这样的语言可以很容易地实现 OO 和 FP,这会影响这两种方法的正交性吗?

I have heard this time and again, and I am trying to understand and validate the idea that FP and OO are orthogonal.

First of all, what does it mean for 2 concepts to be orthogonal?

FP encourages immutability and purity as much as possible, while OO seems built for state and mutation – a slightly organized version of imperative programming? I realize that objects can be immutable, but OO seems to imply state/change to me.

They seem like opposites. How does that affect their orthogonality?

A language like Scala makes it easy to do OO and FP both, does this affect the orthogonality of the two methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

黎夕旧梦 2024-10-04 17:24:57

正交性意味着两件事不相关。它来自数学,意思是垂直。在常见用法中,它可能意味着两个决定不相关,或者一个主题在考虑另一个主题时不相关。正如此处所使用的,正交意味着一个概念既不暗示也不排除另一个概念。

两个概念面向对象编程函数式编程彼此并不兼容。面向对象并不意味着可变性。许多以传统方式接触面向对象程序的人通常首先使用 C++、Java、C# 或类似的语言,在这些语言中,可变性很常见,甚至受到鼓励(标准库提供了各种可变类供人们使用)。因此,许多人将面向对象编程与命令式编程和可变性联系起来是可以理解的,因为这就是他们学习的方式。

然而,面向对象编程涵盖了以下主题:

  • 封装
  • 多态性
  • 抽象

这些都不意味着可变性,也不排除函数式编程。所以,是的,它们是正交的,因为它们是不同的概念。它们并不是对立的——您可以使用其中之一,或使用另一个,或两者都使用(甚至都不使用)。 Scala 和 F# 等语言尝试将两种范式合并为一种语言:

Scala 是一种多范式编程语言,旨在集成面向对象编程和函数式编程的功能。

来源

F# 是一种简洁、富有表现力且高效的函数式面向对象的语言,适用于 .NET,可帮助您编写简单的代码来解决复杂的问题。

来源

Orthogonality implies that two things are unrelated. It comes from mathematics where it means perpendicular. In common usage it can mean two decisions are unrelated or that one subject is irrelevant when considering another subject. As used here, orthogonal means that one concept doesn't either imply or exclude the other.

The two concepts object oriented programming and functional programming are not incompatible with each other. Object orientedness does not imply mutability. Many people who are introduced to object oriented programs the traditional way often first use C++, Java, C# or similar languages where mutability is common and even encouraged (standard libraries provide a varierty of mutable classes for people to use). Therefore it is understandable that many people associate object oriented programming with imperative programming and mutability, as this is how they have learned it.

However object oriented programming covers topics like:

  • Encapsulation
  • Polymorphism
  • Abstraction

None of this implies mutability, and none of it excludes functional programming. So yes they are orthogonal in that they are different concepts. They are not opposites - you can use one, or the other, or both (or even neither). Languages like Scala and F# attempt to combine both paradigms into a single language:

Scala is a multi-paradigm programming language designed to integrate features of object-oriented programming and functional programming.

Source

F# is a succinct, expressive and efficient functional and object-oriented language for .NET which helps you write simple code to solve complex problems.

Source

苍白女子 2024-10-04 17:24:57

首先,两个概念正交是什么意思?

这意味着这两个概念没有对立的想法或彼此不相容。

FP 尽可能鼓励不变性和纯洁性。面向对象似乎是为状态和突变而构建的(命令式编程的稍微组织的版本?)。我确实意识到对象可以是不可变的。但 OO 对我来说似乎意味着状态/变化。

他们看起来是对立的。它如何影响它们的正交性?

像 Scala 这样的语言可以轻松实现 OO 和 FP,这会影响这两种方法的正交性吗?

OO 涉及封装、对象组合、数据抽象、通过子类型实现的多态性以及必要时的受控突变(OO 中也鼓励不变性)。 FP 是关于函数组合、控制抽象和约束多态性(又名参数多态性)。因此这两种想法并不矛盾。它们都为您提供了不同类型的权力和抽象机制,这当然可以在一种语言中拥有。事实上,这正是 Scala 的基础!

Martin Odersky 在 Google 的 Scala Experiment 演讲中很好地解释了他对这两者的看法概念 - OO 和 FP - 彼此正交,以及 Scala 如何优雅且无缝地将这两种范式统一为 Scala 社区中众所周知的新范式,称为对象功能范式。一定要给你看谈话。 :-)


对象功能语言的其他示例:OCamlF#Nemerle

First of all, what does it mean for 2 concepts to be orthogonal ?

It means that the two concepts do not have contrasting ideas or are not incompatible with each other.

FP encourages immutability and purity as much as possible. and OO seems like something that is built for state and mutation(a slightly organized version of imperative programming?). And I do realize that objects can be immutable. But OO seems to imply state/change to me.

They seem like opposites. How does it affect their orthogonality ?

A language like Scala makes it easy to do OO and FP both, does this affect the orthogonality of the 2 methods ?

OO is about encapsulation, object composition, data abstraction, polymorphism via subtyping, and controlled mutation when necessary (immutability is encouraged in OO as well). FP is about function composition, control abstraction, and constrained polymorphism (aka parametric polymorphism). Thus the two ideas are not contradictory. They both provide you with different kinds of powers and abstraction mechanisms, which are certainly possible to have in one language. In fact, this is the thesis on which Scala was built!

In his Scala Experiment talk at Google, Martin Odersky explains it very well how he believes the two concepts - OO and FP - are orthogonal to each other and how Scala unifies the two paradigms elegantly and seamlessly into a new paradigm popularly known in Scala community as object-functional paradigm. Must watch talk for you. :-)


Other examples of object-functional languages: OCaml, F#, Nemerle.

笑,眼淚并存 2024-10-04 17:24:57

首先,两个概念正交是什么意思?

这意味着它们不会互相影响。也就是说,函数式语言并不是因为它也是面向对象的而功能较少。

他们看起来是对立的。它如何影响它们的正交性?

如果它们是对立的(即纯函数式语言不可能是面向对象的),那么根据定义它们就不是正交的。但我不相信事实是这样。

面向对象似乎是为状态和突变而构建的(命令式编程的稍微组织的版本?)。我确实意识到对象可以是不可变的。但 OO 对我来说似乎意味着状态/变化。

虽然对于大多数主流 OO 语言来说都是如此,但 OO 语言没有理由需要具有可变状态。

如果一种语言具有对象、方法、虚拟继承和临时多态性,那么它就是面向对象的语言 - 无论它是否也具有可变状态。

First of all, what does it mean for 2 concepts to be orthogonal?

It means they don't affect each other. I.e. a functional language isn't less functional because it's also object oriented.

They seem like opposites. How does it affect their orthogonality?

If they were opposites (i.e. a purely functional language could not possibly be object oriented), they would by definition not be orthogonal. However I do not believe that this is the case.

and OO seems like something that is built for state and mutation(a slightly organized version of imperative programming?). And I do realize that objects can be immutable. But OO seems to imply state/change to me.

While this is true for most mainstream OO languages, there is no reason that an OO language needs to have mutable state.

If a language has objects, methods, virtual inheritance and ad-hoc polymorphism, it's an object oriented language - whether it also has mutable state or not.

尐籹人 2024-10-04 17:24:57

对于两个概念来说,正交意味着它们可以在任何给定的表现形式中以任何程度独立地实现。例如,考虑到音乐,您可以根据音乐作品的和谐程度和节奏程度对音乐作品进行分类。 “和声”和“节奏”这两个概念是正交的,即存在和声和节奏的作品、不和谐和节奏的作品、以及不和谐和节奏的作品以及和声和节奏的作品。

应用于原始问题,这意味着存在纯函数式、非面向对象的编程语言(例如 Haskell)、纯面向对象的“非函数式”语言(例如 Eiffel),但也存在两者都不是的语言(例如 C)和两者都如Scala。

简单地说,Scala 是面向对象的,意味着您可以定义数据结构(“类”和“特征”),用操作数据的方法封装数据,保证这些结构的实例(“对象”)始终位于一个定义的状态(对象在其类中的契约)。

另一方面,Scala 是一种函数式语言,意味着它更喜欢不可变而不是可变状态,并且函数是第一类对象,可以像任何其他对象一样用作其他函数的局部变量、字段或参数。除此之外,Scala 中几乎每个语句都有一个值,这鼓励您使用函数式编程风格。

Scala 中面向对象编程和函数式编程的正交性还意味着,作为程序员,您可以自由选择您认为适合您目的的这两个概念的任意组合。您可以以纯粹的命令式风格编写程序,仅使用可变对象,而根本不使用函数作为对象,另一方面,您也可以在 Scala 中编写纯函数式程序,而不使用其任何面向对象的功能。

Scala 实际上并不要求您使用其中一种风格。它可以让您选择两全其美的方式来解决您的问题。

For two concepts to be orthogonal means that they can be independently realized to any degree in any given manifestation. Considering music, for instance, you can classify a musical piece as to how harmonic it is and how rhythmic it is. The two concepts "harmonic" and "rhythmic" are orthogonal in the sense that there are harmonic and rhythmic pieces, disharmonic and arrythmic pieces, but also disharmonic and rhythmic pieces as well as harmonic and arrhythmic pieces.

Applied to original question this means that there are purely functional, non-object oriented programming lanuages such as Haskell, purely object-oriented, "non-functional" languages such as Eiffel, but also languages which are neither such as C and languages which are both such as Scala.

Simply speaking, Scala being object-oriented means that you can define data structures ("classes" and "traits") which encapsulate data with the methods that manipulate this data, guaranteeing that instances of these structures ("objects") are always in a defined state (the object's contract laid out in its class).

On the other hand, Scala being a functional language means that it favors immutable over mutable state and that functions are first class objects, which can be used just like any other object as local variables, fields or parameters to other functions. In addition to this, almost every statement in Scala has a value, which encourages you to use a functional programming style.

Orthogonality of object-orientated programming and functional programming in Scala additionaly means that you as a programmer are free to choose any mixture of these two concepts you see fit for your purpose. You can write your programs in a purely imperative style, using mutable objects only and not using functions as objects at all, on the other hand you can also write purely functional programs in Scala not using any of its object-oriented features.

Scala really does not require you to use one style or the other. It lets you choose the best of both worlds to solve your problem.

唯憾梦倾城 2024-10-04 17:24:57

与所有分类一样,将编程语言划分为函数式、面向对象式、过程式等是虚构的。但我们确实需要分类,在编程语言中,我们根据一组语言特征和使用该语言的人的哲学方法(后者受到前者的影响)进行分类。

因此,有时“面向对象”语言可以成功地采用“函数式”编程语言的特性和理念,反之亦然。但当然并非所有编程语言的功能和哲学都是兼容的。

例如,像 OCaml 这样的函数式语言通过词法作用域和闭包来完成封装,而面向对象的语言则使用公共/私有访问修饰符。这些机制本身并不是不兼容的,但它们是多余的,像 F# 这样的语言(一种主要是函数式语言,旨在与绝对面向对象的 .NET 库和语言堆栈和谐相处)必须竭尽全力来桥接差距。

作为另一个例子,OCaml 使用面向对象的结构类型系统,而大多数面向对象的语言使用名义类型系统。这些几乎是不兼容的,有趣的是,它们代表了面向对象语言领域内的不兼容。

Like all classifications, the division of programming languages into functional, object-oriented, procedural, etc. is fictional. But we do need classifications, and in programming languages we classify by a set of language features and the philosophical approach of those who use the language (where the later is influenced by the former).

So sometimes "object-oriented" languages can have success adopting the features and philosophies of "functional" programming languages and vice-versa. But certainly not all programming language features and philosophies are compatible.

For example, a functional language like OCaml accomplishes encapsulation through lexical scoping and closures, whereas a object-oriented languages use public/private access modifiers. These are not incompatible mechanisms per-se, but they are redundant, and a language like F# (a mostly functional language which seeks to live in harmony with the decidedly object-oriented .NET library and language stack) has to go to lengths to bridge the gap.

As another example, OCaml uses a structural type system for object-orientation, whereas most object-oriented languages use a nominal type system. These are pretty-much incompatible, and interestingly represent incompatibility within the realm of object-oriented languages.

苦妄 2024-10-04 17:24:57

对象的想法可以以不可变的方式实现。 Abadi 和 Cardelli 所著的《对象理论》一书就是一个例子,该书旨在将这些想法形式化,并且对象首先被赋予不可变的语义,因为这使得面向对象程序的推理变得更简单。

在这种情况下,传统上会就地修改对象的方法会返回一个新对象,而先前的对象仍然存在。

The idea of objects can be implemented in an immutable fashion. An example is the book "A Theory of Objects", by Abadi and Cardelli, that aims at formalizing these ideas, and where objects are first given immutable semantics because that makes reasoning about object-oriented programs simpler.

In this case, a method that would traditionally have modified the object in-place instead returns a new object, while the previous object persists.

蓝戈者 2024-10-04 17:24:57

您可以将函数实现为对象,也可以将对象实现为函数集合,因此这两个概念之间显然存在某种关系。

FP 尽可能鼓励不变性和纯洁性

您正在谈论函数式编程。

虽然 OO 似乎是为状态和突变而构建的

不要求对象是可变的。我想说对象和变异是正交的概念。例如,OCaml 编程语言提供了纯函数对象更新的语法。

像 Scala 这样的语言可以轻松实现面向对象和函数式编程

事实并非如此。缺乏尾部调用优化意味着大多数惯用的纯函数式代码在 Scala 中会出现堆栈溢出,因为它会泄漏堆栈帧。例如,连续传球风格 (CPS) 以及论文 布鲁斯·麦克亚当 (Bruce McAdam) 的文章就到此结束了。没有简单的方法可以解决这个问题,因为 JVM 本身无法进行尾部调用优化。

关于纯函数式编程和面向对象编程的正交性,我想说它们至少接近正交,因为纯函数式编程仅处理小型程序(例如高阶函数),而面向对象编程则处理大型程序- 计划的规模结构。这就是为什么函数式编程语言通常为大规模结构化提供一些其他机制,例如标准 ML 和 OCaml 的高阶模块系统,或 Common Lisp 的 CLOS 或 Haskell 的类型类。

You can implement functions as objects and objects as collections of functions, so there is clearly some relationship between the two concepts.

FP encourages immutability and purity as much as possible

You are talking about purely functional programming.

while OO seems built for state and mutation

There is no requirement for objects to be mutable. I would say that objects and mutation were orthogonal concepts. For example, the OCaml programming language provides a syntax for purely functional object update.

A language like Scala makes it easy to do OO and FP both

Not really. The lack of tail call optimization means that the majority of idiomatic purely functional code will stack overflow in Scala because it leaks stack frames. For example, continuation passing style (CPS) and all of the techniques described in the paper That about wraps it up by Bruce McAdam. There is no easy way to fix that because the JVM itself is incapable of tail call optimization.

Regarding the orthogonality of purely functional programming and object oriented programming, I would say that they are at least close to being orthogonal simply because purely functional programming deals only with programs in the small (e.g. higher order functions) whereas object oriented programming deals with the large-scale structuring of programs. This is why functional programming languages usually provide some other mechanism for large-scale structuring, e.g. the higher-order module systems of Standard ML and OCaml, or CLOS for Common Lisp or typeclasses for Haskell.

七颜 2024-10-04 17:24:57

帮助我理解 FP 和 OO 之间关系的一件事是 SICP 书,特别是 “函数式程序的模块化和对象的模块化” 如果您正在考虑这些问题并且周末有空,那么前三章可能值得阅读,真是大开眼界。

One thing that helped me understand the relationship between FP and OO was the SICP book, particularly the section "Modularity of Functional Programs and Modularity of Objects" If you are thinking about these issues and you have a spare weekend, it might be worth reading through the first three chapters, its pretty eye opening.

转身泪倾城 2024-10-04 17:24:57

我刚刚发现了一个精彩的 OOP和FP的正交性的解释

基本思路如下。想象一下我们正在使用数学表达式的 AST。所以我们有不同类型的名词(常量、加法、乘法)和不同的动词(eval、toString)。

假设表达式为 (1 + 2) * 3。那么 AST 就是:

       multiplication
         /        \
     addition      3
      /    \
     1      2

为了实现一个动词,我们必须为每种类型的名词提供它的实现。我们可以将其表示为一个表格:

                +---------------------+-------------------------------------+
                | eval                | toString                            |
+---------------+---------------------+-------------------------------------+
| constant      | value               | value.toString                      |
+---------------+---------------------+-------------------------------------+
| addition      | lhs.eval + rhs.eval | lhs.toString + " + " + rhs.toString |
+---------------+---------------------+-------------------------------------+
| mutiplication | lhs.eval * rhs.eval | lhs.toString + " * " + rhs.toString |
+---------------+---------------------+-------------------------------------+

“正交性”来自于这样的事实,在OOP中,我们将按行实现这个表格:我们将把每个名词表示为一个类,它必须实现每个方法。

另一方面,在 FP 中,我们将按列实现此表 - 我们将为每个动词编写一个函数,并且该函数对不同类型的参数会有不同的反应(可能使用模式匹配)。

I’ve just found a wonderful explanation of the orthogonality of OOP and FP.

The basic idea is as follows. Imagine we are working with ASTs of math expressions. So we have different types of nouns (constant, addition, multiplication) and different verbs (eval, toString).

Let’s say, the expression is (1 + 2) * 3. Then the AST would be:

       multiplication
         /        \
     addition      3
      /    \
     1      2

To implement a verb, we have to provide its implementation for every type of noun. We can represent it as a table:

                +---------------------+-------------------------------------+
                | eval                | toString                            |
+---------------+---------------------+-------------------------------------+
| constant      | value               | value.toString                      |
+---------------+---------------------+-------------------------------------+
| addition      | lhs.eval + rhs.eval | lhs.toString + " + " + rhs.toString |
+---------------+---------------------+-------------------------------------+
| mutiplication | lhs.eval * rhs.eval | lhs.toString + " * " + rhs.toString |
+---------------+---------------------+-------------------------------------+

The “orthogonality” comes from the fact, than in OOP we will be implementing this table by rows: we will represent every noun as a class, which will have to implement every method.

In FP, on the other hand, we will implement this table by columns — we will write a function for every verb, and this function will react differently to arguments of different types (using pattern matching probably).

悍妇囚夫 2024-10-04 17:24:57

正交。听起来不错。如果你受过教育,你可以把它绑起来并假装。它有点像范式。

这完全取决于您所处的圈子以及每种类型的编程技术会给您带来什么。我读过一些关于 SS 的文章,大多数来自函数式编程语言的人通常坚持这样一个事实:你只能使用函数式编程,而其他任何事情都违背了思维和思维定势。

面向对象编程主要是捕获状态并尽可能保持该状态本地化,以免受到不属于您管理状态的对象一部分的任何内容的影响。另一方面,函数式编程从不同的角度看待状态问题,并试图将状态与系统分离并将其简化为函数。是的,您可以在代码中使用这两种技术,但它们都从不同的角度来看待软件的设计。

人们对函数式编程技术非常感兴趣,主要是因为在处理多核芯片和并行编程时需要进行状态管理。目前看来,函数式编程在处理这个问题上确实占据了上风,但是您可以使用对象来实现相同的效果。只是你对问题的看法不同而已。您不必绞尽脑汁,尝试尽可能摆脱状态,而是查看设计中的对象,看看如何使用设计模式、CRC 和对象分析。然而,对象确实发挥了作用,而函数式编程更加困难的地方在于分析现实世界并将其映射到可理解的计算机化系统。例如,在面向对象中,人员对象将是状态的封装,其中包含作用于人员状态的方法。在函数式编程中,一个人将被分解为作用于该人数据的数据部分和函数,附加条件是数据应该被创建一次且只能创建一次并且是不可变的。

我必须承认,虽然来自面向对象的背景,但在大多数面向对象语言中,当处理多核芯片时,我已经走了功能路线,主要是通过核心编程设计结构(例如线程和委托)并传递伪数据对象。这让我对面向对象编程的技术产生了疑问,因为它似乎并不能很好地映射到这种线程设计。

Orthogonal. It sounds good. If you got an education you can band it about a bit and pretend. Its a bit like paradigm.

It all depends in which circles you travel in and what each type of programming technique will give you. I have read a few posts on SS and most who come from a functional programming language usual persist on the fact that you can only go functional and anything else goes against the thinking and the mind set.

Object Oriented programming is mainly about capturing state and keeping this state as localised as possible as not to be affected by anything that is not part of the object that you manage the state with. On the other hand, functional programming looks at the problem of state from a different perspective and tries to separate state from the system and reduce it down to functions. Yes you can use both techniques in your code but they both are looking at the design of software from different angles.

There has been a great deal of interest in the techniques of Functional Programming, mainly because of the management required of state when dealing with multi-core chips and parallel programming. It seems at this point in time that functional programming does have the upper hand in dealing with this however you can achieve the same effect using Objects. You just think of the problem differently. Instead of scratching you head, trying to get rid of state as much as possible, you look at objects in the design and see how you can pair them down to what the core of what they are expected to do, using design patterns, CRC and Object Analysis. Where Objects do come into there own though, and where functional programming is a lot more difficult is in analysing the real world and mapping it to an understandable computerised system. In OO for example, a person object would be an encapsulation of state with methods that act upon the persons state. In Functional programming, a person would be broken down into data parts and functions that act upon the person data, with the added proviso that data should be created once and only once and be immutable.

I must admit though coming from an OO background, that in most OO languages when dealing with Multi-core chips, I have gone the functional route, mainly by core programming design structures (such as threads and delegates) and pass pseudo data objects around. This has led me to question the techniques of OO programming as it does not seem to map well to this threaded design.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文