Are FP and OO orthogonal?

2019-01-20 23:44发布

问题:

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?

回答1:

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



回答2:

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.



回答3:

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.



回答4:

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.



回答5:

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.



回答6:

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.



回答7:

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.



回答8:

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.



回答9:

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).



回答10:

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.