Make sure your examples match your claim (case: FP vs. OOP)

I started reading Functional Programming Patterns in Scala and Clojure – a nice book so far. However, right at the beginning in Chapter 1.1 “What is Functional Programming?” the author compares an object-oriented implementation with  a functional implementation. Here is the code, first object-oriented (Java):

public List filterOdds(List list) {
    List filteredList = new ArrayList();
    for (Integer current : list) {
        if (isOdd(current)) {
            filteredList.add(current);
        }
    }
    return filteredList;
}
private boolean isOdd(Integer integer) {
    return 0 != integer % 2;
}

Now functional version (Clojure):

(filter odd? list-of-ints)

After this comparison the author states: “The functional version is obviously much shorter than the object-oriented version.”. Well let’s all just go and do functional programming then!

Not so fast. The object-oriented example has a lot of clutter that has nothing to do with Object-oriented Programming, they are just due to Java or in part due to a somewhat unfair comparison. Let’s walk through the code and remove the clutter to make a better comparison.

Types

The sample features a lot of type information – that has nothing to do with OOP vs. FP, there are also functional languages that have types, although a lot of them handle them better than Java. Let’s Remove them:

public filterOdds(list) {
    filteredList = [];
    for (current : list) {
        if (isOdd(current)) {
            filteredList.add(current);
        }
    }
    return filteredList;
}
private isOdd(integer) {
    return 0 != integer % 2;
}

isOdd method

The Java sample defines a private isOdd method to check if a number is odd. This has nothing to do with OOP, it’s just a detail that Java does not implement an isOdd method themselves. There might also be functional languages out there, that doesn’t have it built in like Clojure. So let’s remove that as well:

public filterOdds(list) {
    filteredList = [];
    for (current : list) {
        if (isOdd(current)) {
            filteredList.add(current);
        }
    }
    return filteredList;
}

 

Method definition

The Clojure version does not define a method while the Java version defines a method. So let’s remove that method definition from the Java code. I also omit the return statement, because the result is now saved in the filteredList, which can be used for further computation.

filteredList = [];
for (current : list) {
    if (isOdd(current)) {
        filteredList.add(current);
    }
}

Be careful with your comparisons

Compare the final code sample with what we started out with. It’s half the lines of code and much more concise. I stripped off parts of the code that I believe have nothing to do with the argument at hand, but are rather details of Java. I still like the Clojure sample better and I’d also prefer coding Clojure over Java any day of the week. That’s not the point.

The point is that one should be diligent to make examples for comparisons stick to the topic at hand. And in the book the topic was FP vs. OOP – not Java vs. Clojure.

On a final note, a lot of cool mainly object-oriented languages have features akin to these of functional programming. Often in the shape of blocks. Let’s take a look at Smalltalk, the language that is often credited with introducing Object-oriented Programming. Let’s implement our little code sample there (I used GNU Smalltalk, which implements Smalltalk-80, the “original”):

ints select: [:i | i odd]

That’s short and sweet! Now, just for kicks, let’s do ruby, which is mainly object-oriented, but well luckily has these functional features:

ints.select &:odd?

Just saying, be careful with your examples. These two (mainly) object-oriented languages do just as well as Clojure here.

Last but not least, let it be duly noted, that yes the Clojure result is lazy and immutable, but then again that’s not the point here, although both are col features 😉

3 thoughts on “Make sure your examples match your claim (case: FP vs. OOP)

  1. I was going to comment that `ints.select &:odd?` only works with Rails but I just discovered Symbol#to_proc made its way into stdlib in 1.9.3, wow!

    1. 🙂 Yeah and it’s optimized, so it’s also slightly faster than the more verbose version.

      Related, I learned two days ago that rubocop complains about an ambiguous operator if you leave out the parentheses (could be binary and) – might fix that up

  2. Correct examples have so much to do with correct understanding. The original example actually appears very lame. Object-Oriented is amazing and we programmers are already reaping its benefits since years now. It still feels so good when even in a very large application, a piece of code is changed/added and we are sure that it does NOT shake the existing functionality.

    On the same lines of having correct examples, we started introducing OOP in a rather simplified manner. There is a recent blog post about the same http://kossip.ameyo.com/2014/11/25/the-unusual-approach-to-object-oriented-programming/

Leave a comment