Functional Programming vs OOPS : Explain Like I'm Five

nijeesh4all profile image Nijeesh Joshy ・1 min read

what is the difference between Functional Programming vs OOPS


markdown guide

Imagine three people sitting in a room, lets call them Anna, Brad and Carol.

In object oriented programming, Anna has a paper with cats written on it, and Brad has a paper with are cool written on it. Then Carol comes and asks Brad what do you think?. Brad asks Anna what do you have?, Anna looks at her paper and answers cats. Brad then looks at his paper and answers to Carol Cats are cool.

In functional programming, Carol comes and asks What do you think? then Anna produces a piece of paper, writes cats on it and passes it to Brad. Brad looks at the paper and writes are cool next to cats. Then they hand out the paper to Carol and she reads cats are cool.


Brad looks at the paper and writes are cool next to cats.

Brad looks at Anna’s paper, throws it out and writes on its own paper: “Cats are cool.” Immutability is the word.



Yeah, you're right. I wondered how to include immutability, but I figured discarding the first paper would confuse a 5yo more than anything. Maybe they would just accept that one can not modify the paper once it's passed, though, I should not underestimate them.

Perhaps the writing fills the entire piece of paper, thus there’s no room to write anymore, which might necessitate either
1) re-writing on a new piece of paper or
2) taping/concatenating that paper with a new piece of paper that says “are cool”?

This analogy of taping may still be non-ideal.


Functional is based on functions and OOP (Object Oriented Programming) is based on objects. It's two distinct ways to write code. It's not the only two nor they are mutually exclusive. While OOP tends to replicate the real world with objects you act on, functional is way too abstract for a five year old. It's more like a flow of actions rather than objects interacting with each others.

Consider this recipe:


const crepe = step([
  () => [getFlour(300), getEggs(3), getMilk(60)],


const flour = new Ingredient("flour", 300);
const eggs = new Ingredient("egg", 3);
const milk = new Ingredient("milk", 60);

const crepe = new Recipe();
crepe.mix(flour, eggs, milk).cook();

Ooof! I can't blame you for being confused here. The definitions of "functional programming," "object-oriented-programming," "logic programming," or any other programming paradigm out there aren't set in stone. In a practical sense, they shouldn't be. It matters more how any given language uses functional ideas, or object-oriented ideas.

(This is even more true nowadays than it was forty years ago. Forty years ago, there were languages that were "purely" functional, or "purely" logic-oriented. But today, most commonly used languages are "multi-paradigm." They incorporate ideas from FP, OOP, and other programming styles, but they aren't just one thing. When we say that a modern language is a functional language, or an object-oriented language, usually we mean that it's "mostly" functional or "mostly" OO.)

In general, when you're doing functional programming, you think about "functions" as the basic unit of the language. Functions can be passed around like variables, and you can assemble other mega-functions out of functions. If you wanted to sum a list of numbers, you wouldn't use a for loop. You'd use a special function called a reduce that applied the add function to every number in the list.

add(1, 2)
=> 3
sum = reduce(0, add)
sum([1, 2, 3])
=> 6

When you're doing object-oriented programming, you think about functions as being attached to data. Instead of having an add function that operates on two numbers, you make every number have an add function be attached to it. Or every cat have a meow function attached to it.

3.add(4) => 7
cat.meow() => "meow!"

Different styles are suited for different things! For example, if I'm doing math, I usually find functional programming easier to think about. To me, add(1,2) is simpler than 1.add(2). But if I'm doing other things, I often have an easier time with object-oriented programming. It's easier for me to think about a cat meowing than about a meow function that takes a cat.

Everyone has their favorite style of code, and every language implements these paradigms differently. That's why there are so many definitions of FP and OOP out there! Let's say that someone really likes Haskell. They like it both because they can define functions in terms of other functions (which is a FP thing) and because it has an awesome type-checker (which some, but not all, FP languages have). Because they love Haskell, they love functional programming. But when they talk about functional programming, they often talk about the things they love about Haskell's version of it, not functional programming in general. So people talk about FP as about "immutability" and "type checking" and stuff like that, rather than "building functions out of other functions," and everyone's definitions get confused. :(

The same thing happens on the OOP side! Some folks love using inheritance to organize their code. Inheritance is more common in object-oriented languages than it is in functional ones, so people talk about inheritance like it's necessarily an OOP thing. But! There are also object-oriented languages that don't do inheritance (Rust, arguably). And Haskell's "newtype deriving" isn't called inheritance, but it's basically inheritance. Similarly, just because we think of static type checkers in FP more often, there are totally FP languages without them (Erlang, Elixir) and OOP languages with them. (Java).

People say a lot of things about OOP and FP. A lot of the time, it's to justify why they think that one of them is better than the other. They'll say things like:

OOP is easier to understand in complex systems because objects maintain their own state. Stuff that's far away from the object I'm working with can't affect my code.


FP is better than OOP, because immutability means that I never need to deal with state bugs.

These statements tend to get truer if we sprinkle phrases like "for me" and "usually" through them. So we can translate the above statements into:

I usually think that OOP is easier to understand in complex systems because in my style of OOP objects maintain their own state. Stuff that's far away from the object I'm working with usually can't affect my code.

I think FP is better than OOP, because in functional languages with immutability, I never need to deal with state bugs within a single function.

In general, I wouldn't sweat the difference between FP and OOP too much! Instead, I would look for what aspects of a language make you feel more confident in the code you're writing. When you're looking for teams to work with, seek out people who value those aspects! You'll find each other's code much easier to read than code written by people who value different things.


Why not lol:

Programming is like lego. You build stuff by stacking blocks together.

In FP blocks are functions.

In OOP blocks are classes.

That's a very rudimentary explanation 😉


Ah yes! Wonderful!

What are the connection points between each LEGO?


They could be method invocations, shared state (which I don't suggest overall), asynchronous messages, etc.


I know, I am late to the party, but functional programming and OOP are not exclusive. You can have things like classes, inheritance and polymorphism in pure functional code. Have a look at this Scala code:

abstract class SimpleList[+T] {
  def head: T
  def tail: SimpleList[T]
  def isEmpty: Boolean
  def length: Int

  def ::[S >: T] (newHead: S): SimpleList[S] = new ListNode(newHead, this)

class ListNode[T](hd: T, tl: SimpleList[T]) extends SimpleList[T] {
  override def head = hd
  override def tail = tl
  override def isEmpty = false
  override def length = 1 + tail.length

object EmptyList extends SimpleList[Nothing] {
  override def head = throw new NoSuchElementException
  override def tail = throw new NoSuchElementException
  override def isEmpty = true
  override def length: Int = 0

val squareNumbers = 1 :: 4 :: 9 :: 16 :: EmptyList

We have a immutable list class that stores no mutable state, but uses all features of OO design. By definition of the pure functional paradigm this is also pure functional code.

It is a common misconception that fp and oop are exclusive.


FP vs OOP is a false dichotomy.

FP is about lacking side-effects, or as I like to think about it, having a complete type system (over both data and effects). It's a subset of declarative programming, which in turn is the opposite of imperative programming.

OO is a guideline usually applied in imperative languages that advocates constructing a solution in terms of 'objects' which have predefined ways in which they can be accessed.

Functional style is a guideline applied on both declarative and imperative languages that advocates passing functions around as arguments to other functions.

In theory you can combine OO and functional styles but it's rare, as limiting the interaction you can have with an object seems to go against the notion of passing arbitrary functions. But I've seen it done in Scala for big data analysis.

OO generally expects mutability of objects, which can be a side-effect and therefore appears to be incompatible with FP. This can be resolved by making all objects linear types (or uniqueness types), or simply by dropping mutability.


Want to get s**t done, but suffer from errors? Use OOP.

Want to achieve grail of programming and minimize number of errors, but waste few years (decades?) for education? Use FP.


Well, I could not disagree more.

Everybody can easily produce fully functional code having a gazillion of errors in 10 minutes.


You probably missed the "waste few years (decades?) for education" part. Of course, having superficial knowledge of FP not only will lead to many errors, but probably will make impossible to write real FP code. You also might have missed "minimize number of errors" part. I mean you can minimize them, but not eliminate. And FP is really less error-prone compared to OOP, because there is almost nothing that can break in a small, tested, pure function, or in a chain of such functions. But the hard part is... there are gazillion of functions and you have to remember how they work.

FP is really less error-prone compared to OOP

I doubt. The bottleneck is always the developer. Good developers make fewer errors than bad developers, no matter is it FP, OOP or COBOL.

Well I saw your background thank you for sharing this observation from the "inside". It is very valuable.