Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I'm curious about this because I recall before learning any functional languages, I thought them all horribly, awfully, terribly unreadable. Now that I know Haskell and f#, I find it takes a little longer to read less code, but that little code does far more than an equivalent amount would in an imperative language, so it feels like a net gain and I'm not extremely practiced in functional.

Here's my question, I constantly hear from OOP folks that functional style is terribly unreadable. I'm curious if this is the case and I'm deluding myself, or if they took the time to learn a functional language, the whole style would no longer be more unreadable than OOP?

Has anybody seen any evidence or got any anecdotes where they saw this go one way or another with frequency enough to possibly say? If writing functionally really is of lower readability then I don't want to keep using it, but I really don't know if that's the case or not..

share|improve this question
1  
I remember looking at the code for "Super Nario Brothers" svn.coderepos.org/share/lang/haskell/nario when I barely knew anything about functional programming and remember thinking 'Wow. This seems really readable' –  WuHoUnited Sep 2 '12 at 12:19
    
Take a look at programmers.stackexchange.com/questions/158715/… –  superM Sep 2 '12 at 14:26
add comment

5 Answers 5

up vote 5 down vote accepted

Code readability is very subjective. Because of this, different people would consider the same code readable or unreadable.

An assignment, x = x + 1 sounds weird to a mathematician, because an assignment looks misleadingly similar to a comparison.

A simple OOP design pattern would be totally unclear for someone who is not familiar with these patterns. Consider singleton. Someone would ask "Why do I need a private constructor? What is the mysterious method getInstance() ? Why don't we make a global variable and assign an object there?"

The very same applies to an FP code. Unless you know the logical patterns behind the scenes, it will be very difficult even to understand something very basic, e.g. how to pass a function as an argument to another function.

Having this said, one should understand that FP is not a silver bullet. There are many applications where FP would be difficult to apply and therefore, it will lead to a worse readable code.

share|improve this answer
add comment

Short answer:

One of the elements which make people say that functional programming code is difficult to read is that it gives preference to a more compact syntax.

Long answer:

Functional programming itself cannot be readable or unreadable, since it's a paradigm, not a style of writing code. In C# for example, functional programming looks like:

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

and would be considered readable by any person with enough experience in Java, C# or similar languages.

The language syntax, on the other hand, is more compact for many functional languages (including Haskell and F#) compared to popular OOP languages, giving a preference to symbols rather than word in plain English.

This applies to languages outside FP as well. If you compare popular OOP languages to some less popular which tend to use more English words, the last ones would feel easier to understand for people with no programming experience.

Compare:

public void IsWithinRanges<T>(T number, param Range<T>[] ranges) where T : INumeric
{
    foreach (var range in ranges)
    {
        if (number >= range.Left && number <= range.Right)
        {
            return true;
        }
    }

    return false;
}

to:

public function void IsWithinRanges
    with parameters T number, param array of (Range of T) ranges
    using generic type T
    given that T implements INumeric
{
    for each (var range in ranges)
    {
        if (number is from range.Left to range.Right)
        {
            return true;
        }
    }

    return false;
}

In the same way:

var a = ((b - c) in 1..n) ? d : 0;

could be expressed in an imaginary language as:

define variable a being equal to d if (b minus c) is between 1 and n or 0 otherwise;

When shorter syntax is better?

While more verbose syntax is easier to understand for a beginner, more compact syntax is easier for experienced developers. Shorter code means less characters to type, which means more productivity.

Especially, it really doesn't make sense forcing a person to type a keyword to indicate something which may be deduced from the syntax.

Examples:

  • In PHP you need to type function before every function or method, with no specific reason to do it.

  • Ada always horrified me for forcing the developers to type lots of English words, especially since there is no correct IDE with auto-completion. I haven't used Ada recently and their official tutorial is down so I can't give an example; if anybody has an example, feel free to modify my answer.

  • The syntax 1..n, used in many FP (and Matlab), could be replaced by between 1, n or between 1 and n or between (1, n). The between keyword makes it much easier to understand for people who are not familiar with the language syntax, but still, two dots are much faster to type.

share|improve this answer
5  
I agree with the sentiment, but for different reasons. It's not about how easily an expert can write code, as code is generally read far more often than it is written. Shorter code can also help readability, by not wasting precious time, screen space, and mental capacity if something would already be obvious from a shorter indicator (for instance, newlines instead of semicolons, the two coincidence anyway). It can also hurt when it becomes too cryptic (for instance, I prefer for x in xs over for x xs, because it helps me distinguishing loop variable and container). –  delnan Sep 2 '12 at 12:38
    
Many of the people who I find complain about FP complain as well about the C# snippet you listed as you said, it is also an example of FP. Perhaps this is more an issue of my colleagues than the readability if most OOP people find that snippet readable, though I'm not completely convinced most OOP folks do from my experiences.. thus why I feel so unsure about this topic. –  Jimmy Hoffa Sep 2 '12 at 16:36
    
@Jimmy Hoffa: See programmers.stackexchange.com/a/158721/6605 where I discuss exactly the C# snippet and how it is perceived by beginner programmers. –  MainMa Sep 2 '12 at 17:13
1  
@Sergiy: in Java or C#, a method signature doesn't have method keyword in it. Example: public int ComputePrice(Product product). Adding such keyword, as what PHP did, just adds clutter instead of making things easier to read. If a programmer is unable to understand that a function is a function from its signature, either this programmer has no experience whatsoever, or the code is much more unreadable than the worst piece code I've ever seen. –  MainMa Jan 8 at 10:56
1  
@Sergiy: there are cases where verbosity can help (otherwise, we would see languages and code such as p i ComputePrice(product): _.unitPrice * ~.cart[_]), but some languages push it too far. The example of the redundant function keyword in PHP is a good example. –  MainMa Jan 8 at 11:00
show 3 more comments

I think one of the reasons is that functional programming tends to work with much more abstract concepts. This makes code shorter and more readable for people who know and understand the concepts (because they aptly expresses the essence of the problem), but it is unreadable for people who are not familiar with them.

For example, for a functional programmer it is natural to write a code that can fail at different points within the Maybe monad, or Either monad. Or, to write a stateful computation with the help of the State monad. But for someone who doesn't understand the concept of monads, this all seems like some kind of black sorcery.

So I think it'd be reasonable to use bits of functional programming even in a team of OOP people, as long as one use concepts that are easy to understand or learn, like mapping over a collection with a function or closures.

(And of course, it also depends on the programmer who wrote some piece of code. You can write horribly unreadable code in any language, as well as you can write in a nice and clean style.)

share|improve this answer
add comment

Readability has nothing to do with the paradigms, models and such. The more code reflects the semantics of your problem domain, the more it is operating a terminology and idioms of such a problem domain, the more readable it is.

This is the reason why OOP code is not that readable at all: not that many real world problems are naturally expressed in terms of hierarchical taxonomies. Objects passing messages to each other is a weird concept, and it is very far from anything "real". Surprisingly, there are much more real world concepts that can be naturally mapped to the functional idioms. Problems tend to be defined declaratively, therefore a declarative solution is more natural.

Although, there are many other semantics that could be closer to the real world than a pure functional, pure OOP, pure dataflow or pure whatever would ever be. And due to this fact, a language-oriented approach to problem solving produces the most readable code, beating all the existing "pure" paradigms. With the domain-specific languages, every problem is expressed in its own natural terminology. And functional languages are slightly better than the OOP mainstream stuff in facilitating DSLs implementation (although, much better approaches are available).

share|improve this answer
add comment

Code readability is subjective. I'm sure that some people criticise it through lack of understanding. There are are naturally different idioms in the way common patterns are implemented. For example, the Visitor pattern doesn't really make sense in a language with pattern matching.

Type inference can be a tricky feature. Usually, it's a great accelerator of development, however, it can sometimes be difficult to figure out what types are involved due to the lack of context leading to confusing errors. This is not limited to what Functional Programming languages - I've seen it in C++ templates too!

Modern languages tend to be multi-paradigm. This includes both C# and F#. It is possible to write a functional style in C# and an imperative style in F#. The same people who criticise Functional languages probably write functional code in their object oriented language.

Commercial development in Functional languages is still relatively immature. I've seen a number of mistakes made that would be considered bad form in any language. Such as:

  1. Changing style as you learn the language (and not refactoring) leading to inconsistency.
  2. Too much in one file.
  3. Too many statements on one line.
share|improve this answer
    
Concerning mistakes I'd also add: 4. Overuse of symbols, e.g.: ~@#$%^&*()-_+=\|/.,; 5. Implicit features: optional declarations/keywords/statements, implicit conversions, etc.; –  Sergiy Jan 8 at 10:57
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.