[MergeMe with OoVsFunctional somehow.]
Here we discuss the relation between FunctionalProgramming
(FP) and ObjectOrientedProgramming
(OO(P)). Is it possible to combine both? And why would one want to do that?
In the impure FunctionalProgrammingLanguage
, it is possible to create your own object system. As I understand it, the CommonLispObjectSystem
was also the first in any language to receive an ANSI standard, even before CeePlusPlus
(!), and it has some interesting abilities not found in the object systems of other languages (e.g., MultipleDispatch
There is a concept of "FunctionalObject?
s" (a.k.a. ValueObject
s). Such an object, instead of changing state, returns a copy of itself with changed state. You see them quite often in "non-functional" people's programs, too...
It's been a few years since I've looked at FunctionalProgramming
but it's very unlike ObjectOrientedProgramming
means no SideEffect
s so that a function's behaviour is entirely determined by its arguments. The grand benefit is that if you test a function once then it will always work. The downside is that the entire state of the program must be passed on the stack to every function [Wrong. Much of the program state is on, or accessible via, the stack, but not
passed to every function.]
?) hide this from the programmer somewhat.
Well, you can pass the entire state, but then you are not really taking advantage of functional programming, because then the result of the function still depends on the complete state. Rather, you want the result of a function to depend only on a small set of explicit input parameters. Moreover, I think that limiting SideEffect
s is a good idea in any programming language - side effects are a very good rope to hang yourself with. The problem is that when you take a look at a language like HaskellLanguage
, that does non-strict evaluation, then if you have side effects (which you can
have in most implementations, if you really feel like it), you will soon find out that the hang-yourself-with capacities of side-effects are greatly amplified.
It depends on how you characterize OO. One useful definition is:
- Abstract data types
- Automated memory management
In other words, identity and mutable state don't get a look in. This fits conventional OO languages like SmalltalkLanguage
, but can also fit functional (and logical) languages too. I would argue that it captures the essence of OO, as compared with previous paradigms, better than stateful definitions. -- DaveHarris
[Actually it fits everything but stone age Pascal, C, Fortran, Cobol and Algol. This definition is about as useful as "There are only OO languages and macro assemblers." I take this as more evidence that OO is no paradigm but merely a set of conventions.]
The original definition of OO as far as I can remember it contained three elements:
That's it, no more and no less. -- PhilGoodwin
"Encapsulation" is a misunderstood word; some people say it implies information hiding and some it doesn't. Personally I like to keep the notions separate, but Encapsulation + Information Hiding = Abstract Data Types. So I doubt we disagree fundamentally here.
"Inheritance" excludes delegation; I think this just expresses ignorance of how cool delegation is (reasonable in an old definition, but there's no need to perpetuate it). They are very tightly related, especially if you have direct language support (which most common languages don't).
"Polymorphism" - no argument.
Automated memory management is something I throw in to wind up the CeePlusPlus
crowd. (I'm sure I got it from an article in the early ByteMagazine
special edition, which will have predated C++.) So really we're pretty close.
I need object identity as a core concept. I need to have inheritance and polymorphism to construct frameworks. They can be mimicked with some sort of delegation, that's all right with me. But these three things I feel I must have. I haven't seen them yet in a FunctionalProgrammingLanguage, and have doubts it can be done. -- AlistairCockburn
I agree. My take on much of FP is that it is a way of eliminating identity. Face it, identity only matters when something changes. If a thing can't change then any other one that looks the same will do. I'm skeptical of FP for large-scale systems. I wonder about maintainability. OTOH, I find myself programming in a more ValueOrientedProgramming?
style recently. -- MichaelFeathers
I actually like delegation much more than implementation inheritance and wish that there was a popular non-interpreted language that supported it. You got me on GarbageCollection
. I think that the ideal system would have garbage collection be optional
. I think that you can do that if the references are more than just pointers, but that's a different discussion.
And, since you guys brought up identity and functional programming in the same breath: have you looked at the stuff I've been writing about ObjectFunctionalPatterns
? I suspect that object identity is a basic assumption of OO - not part of its definition, but only because nobody thought to question the assumption at all. Now that it's been questioned I think that it's undeniably part of OO. Of course with identity comes mutable state and with mutability comes the concept of time and ordering - all undoubtedly important to OO whether they are part of its definition or not. -- PhilGoodwin
- Who said that object identity wasn't encompassed by FP? It is, it's just that FP defines "identity" as "state." A number object holding a hex 0x01 has the same identity as any other number object holding a hex 0x01, and a different identity from objects which don't hold numbers, or number objects holding, say, 0xFF or 0xDEADBEEF. If it bugs you, think of it as every object using the InstanceFlyweightPattern, except the compiler can ignore that to give you more speed.
- From what I understand, what they mean by object identity is pretty much that it isn't using the InstanceFlyweightPattern. I.e. that there is more to its identity than its state.
Everyone, take a look at O'Haskell
. An object-oriented functional language based on HaskellLanguage
. Having seen mostly examples with imperative-style programming so far, which perhaps may not seem too worthwhile, I am not yet ready to pass judgment on this.
In any case, taking over some things from the FunctionalProgramming
world is cool regardless:
s associate polymorphism with subtyping. Most FP languages make use of ParametricPolymorphism
. (Sure, there are templates in CeePlusPlus
for this but it is not really the same.)
In an OO-FP language you (should) get both. This particular language also has some other basic foundations, such as built in concurrency. (All objects are active objects - running their own thread).
My take: FunctionalProgramming
is about minimizing state, and ObjectOrientation
is about managing it. You don't want to do stateful objects in a SideEffect
-free language, but you can gain the AdvantagesOfFunctionalProgramming
in any language.
Some languages make it easier than others, of course. For example, iterators always struck me as a needless multiplication of entities; I'd rather be mapping a function over the collection.
How do you characterize OO? AFAICT, the characteristics all OO languages have in common are object identity, and InclusionalPolymorphism?
OO (Inclusional) Polymorphism
Most OO programmers probably think of polymorphism in the ObjectOriented
sense, which is substituting a sub-type where a given type is expected. This is inclusional polymorphism (see also LiskovSubstitutionPrinciple
, this is something similar, if not the same thing). However, there are a number of types of polymorphism:
- ParametricPolymorphism: a.k.a templates or generic types. Where we expect objects to be the same type, but we don't care what that type actually is (e.g., collections). This is a way to specify related types that is orthogonal to inheritance.
- Function-dispatch: calling the appropriate method given the type of the argument. Inheritance provides a means for defining type-relationships, which is a concise way of specifying to which types functions apply.
So-called "inclusional" polymorphism is merely a degenerate form of MultipleDispatch
that only allows polymorphism on the first parameter to a function. OperatorOverloading
is the same as defining a method that takes the same number of arguments as the operator, so is also the same as multiple dispatch.
The two above items both show that polymorphism is merely a way of defining types, and how functions apply to those types, so in fact we have only one kind of polymorphism.
For example, JavaLanguage
supports only inclusional polymorphism (through class inheritance and/or interfaces). CeePlusPlus
supports inclusional (single and multiple inheritance), parametric (templates), and AdHocPolymorphism
. The interesting thing with C++ is the use of MultipleInheritance
to allow a given type to be a sub-type of many (possibly unrelated) types. Java uses interfaces, and Ruby uses MixIn
s to the same end.
OO Feature Check
Some (for example, see Booch's ObjectOrientedAnalysisAndDesign
) will claim that an ComponentOrientedLanguage
should have some or all of:
- Inclusional polymorphism
- Abstract datatypes
(How is delegation a separate characteristic? Someone help me here because currently I simply see delegation as an consequence of inclusional polymorphism.)
Inheritance is a RedHerring.
You only need it in languages such as CeePlusPlus
because it is the only way to achieve sub-typing. EmeraldLanguage?
(http://www.cs.ubc.ca/nest/dsg/emerald.html [BrokenLink 2005-08-31]
- alt, see http://www.cs.ubc.ca/~norm/emerald.html
(2007-01-23)) is an example of an ObjectOrientedLanguage
which does not have any form of inheritance, yet I consider it to be OO because it supports inclusional polymorphism (and object identity). Emerald uses contra-variance to achieve sub-typing; see ContraVsCoVariance
I've read claims that behavioural reuse (as opposed to interface reuse) through inheritance is just as important. However, you can achieve behavioural reuse through composition, so you really gain nothing. Composition also reduces dependency, which is a GoodThing
(composition is advocated by the GangOfFour
Many languages support encapsulation, modularity, and abstract datatypes, yet they do not claim to be OO. Examples: MlLanguage
, (old, pre-OO) AdaLanguage
, Oracle's PlSql
(The version bundled with the 7.3 RDBMS. Later versions of Oracle (8) have added objects/classes etc. AFAIK PL/SQL was inspired by Ada.) So I would say that these are not defining characteristics of OO languages, though clearly desirable (and apparently ubiquitous - can you name an OO language which does not support these concepts?).
FunctionalProgramming Feature Check
Some modern FunctionalProgrammingLanguage
s also support these concepts, and also inclusional polymorphism. HaskellLanguage
looks like it supports inclusional polymorphism through type classes, but it doesn't (not yet, anyway. Type classes are exactly that: classes of types, i.e., they are not types. You could best think of them as constraints on types.) Haskell is also not OO because it has no notion of object identity.
FP deals purely with data. You can think of a purely functional program as creating, copying, and passing around many immutable objects. (Because objects are immutable, everything can be passed by reference [PassByReference
]. All storage is allocated on the heap, so the stack is only used for passing pointers to heap objects.)
FP languages also differ significantly in that they treat functions (and LexicalClosures?
) as FirstClass
objects, so they can be passed to other functions like objects/data. FP is typified by HigherOrderFunction
s: functions that take functions as arguments and return functions. This can be achieved in OO languages (see BlocksInJava
) but it's somewhat cumbersome, and there is no static type checking (anyway, weren't these ideas were inspired-by/borrowed-from FP languages? - see FunctionalPatternSystemForObjectOrientedDesign
). I am aware that SmalltalkLanguage
supports lexical closures, but again no static type checking.
can support the missing OO concepts (object identity and state) through Monads. Most (all) aspects of SideEffect
-based programming can be modelled with Monads, while still retaining ReferentialTransparency
, which is one of the claimed AdvantagesOfFunctionalProgramming
. (See OnMonads
Monads are not the only abstraction in functional programming, and they are not the most useful one. I wish this misconception would stop being parroted.
I wrote this a while ago and it looks like a pile of poo now. But I suppose it is a milestone for my understanding of type systems at the time. A little knowledge is a dangerous thing... http://www.apa.org/journals/psp/psp7761121.html. (BrokenLink 2005-08-31)
OnUnderstandingTypes, Data Abstraction, and Polymorphism (1985). LucaCardelli, PeterWegner. ACM Computing Surveys. http://citeseer.nj.nec.com/cardelli85understanding.html (BrokenLink 2005-08-31)
for a FunctionalProgrammingLanguage
with OO bolted on. Ocaml has also a very sophisticated type system where subtyping is not inheritance-based.
At the limits:
- Functional programming treats everything as a program, even data.
- Object-oriented programming treats everything as data, even programs.
This page has an "article mode" version in the June 2005 issue of The Monad.Reader - http://www.haskell.org/tmrwiki/FpVsOo
, thanks to AlistairBayley
. -- ShaeErisson
Over the broad middle ground, we choose when to treat something as program and when to treat it as data: NiceLanguage