Functional Programming vs. OOP – Comparing with Classes

functional programmingobject-orientedpythonscala

I have been interested in some of the concepts of functional programming lately. I have used OOP for some time now. I can see how I would build a fairly complex app in OOP. Each object would know how to do things that object does. Or anything it's parents class does as well. So I can simply tell Person().speak() to make the person talk.

But how do I do similar things in functional programming? I see how functions are first class items. But that function only does one specific thing. Would I simply have a say() method floating around and call it with an equivalent of Person() argument so I know what kind of thing is saying something?

So I can see the simple things, just how would I do the comparable of OOP and objects in functional programming, so I can modularize and organize my code base?

For reference, my primary experience with OOP is Python, PHP, and some C#. The languages that I am looking at that have functional features are Scala and Haskell. Though I am leaning towards Scala.

Basic Example (Python):

Animal(object):
    def say(self, what):
        print(what)

Dog(Animal):
    def say(self, what):
        super().say('dog barks: {0}'.format(what))

Cat(Animal):
    def say(self, what):
        super().say('cat meows: {0}'.format(what))

dog = Dog()
cat = Cat()
dog.say('ruff')
cat.say('purr')

Best Answer

What you are really asking about here is how to do Polymorphism in functional languages, i.e. how to create functions that behave differently based on their arguments.

Note the first argument to a function is typically equivalent to the "object" in OOP, but in functional languages you usually want to separate functions from data, so the "object" is likely to be a pure (immutable) data value.

Functional languages in general provide various options for achieving polymorphism:

  • Something like multimethods which call a different function based on examining the arguments provided. This can be done on the type of the first argument (which is effectively equal to the behaviour of most OOP languages), but could also be done on other attributes of the arguments.
  • Prototype / object-like data structures which contain first-class functions as members. So you could embed a "say" function inside your dog and cat data structures. Effectively you have made the code part of the data.
  • Pattern matching - where pattern matching logic is built into the function definition, and ensures different behaviours for different parameters. Common in Haskell.
  • Branching / conditions - equivalent to if / else clauses in OOP. Might not be highly extensible, but can still be appropriate in many cases when you have a limited set of possible values (e.g. was the function passed a number or a string or null?)

As an example, here's a Clojure implementation of your problem using multimethods:

;; define a multimethod, that dispatched on the ":type" keyword
(defmulti say :type)  

;; define specific methods for each possible value of :type. You can add more later
(defmethod say :cat [animal what] (println (str "Car purrs: " what)))
(defmethod say :dog [animal what] (println (str "Dog barks: " what)))
(defmethod say :default [animal what] (println (str "Unknown noise: " what)))

(say {:type :dog} "ruff")
=> Dog barks: ruff

(say {:type :ape} "ook")
=> Unknown noise: ook

Note that this behaviour doesn't require any explicit classes to be defined: regular maps work fine. The dispatch function (:type in this case) could be any arbitrary function of the arguments.