13

Background: I am proponent of functional programming who works at a VB.NET shop where the prevailing mental model is imperative programming. Being that foundation of our system is WinForms I can understand we're not going to get entirely away from imperative programming, but still I try to use FP (primarily via Linq) wherever possible because I believe in its merits.

Arguments & counter-arguments against FP

  1. One might notice that fluent Linq is less efficient than its imperative counterpart in that this style processes a sequence down to another sequence and repeats that. Generally, its going to take a few more passes than the imperative approach which can be better optimized to avoid repeat passes over a sequence. For this reason, the lead couldn't understand why I would choose a functional approach that is clearly "less efficient."

    • Counter-argument: I argued that while it is sometimes less efficient in terms of CPU cycles, that I felt it is more humanly intelligible and easy to follow since each line does just one thing on its pass over the sequence. To me this feels like having an assembly line where each person at his station has just one job to do. I feel that the negligible trade off of efficiency is recompensed by code whose concerns are neatly separated.
  2. The next argument against FP that I hear in my shop is that it's harder to debug -- which is true. It's not easy to step over Linq code. And I do sometimes have to unravel a method chain in order to better follow and dissect issues that I can't immediately spot.

    • _Counter-argument: For the most part though I don't have issue with this because I think the functional style is more declarative in how it reads and when an error is thrown within a functional chain, I can usually spot the issue immediately.

My Question

I've been trying to promote functional style in our shop and I don't feel like I'm making headway. I've done both styles of programming and have only recently dabbled in Haskell. Despite years of imperative experience, now that I'm making routine use of FP in JavaScript, it's grown on me. It rings a note of rightness in my core when I compare it to what I might have done if I stuck to an imperative style. I've retrained my brain toward functional thinking, toward functional composition.

What I can't understand is how hard its been to convince others of FP's merits.

For example, the developers in my shop do use Linq, but I think they generally use it in the context of dealing with domain data. I use it in a more general sense and prefer it anytime I'm dealing with sequences/lists or persistent data structures. I haven't been able to convince my teammates to expand their use of Linq.

What I'm trying to understand is what causes a developer to not like FP.

I would like to see an answer from someone who has a good deal of experience with FP but decided in favor of the imperative style. What drove the decision to stay with imperative instead of using functional?


Here's an additional example highlighting the differences between imperative & functional programming.

I wrote the SelectedRows method of our grid in Linq as such:

Public Property SelectedRows() As DataRow() Implements IDataSourceControl.SelectedRows
    Get
        Return Me.ugrBase.Selected.Rows.
            OfType(Of Infragistics.Win.UltraWinGrid.UltraGridRow)().
            Select(Function(ugr) ugr.ListObject).
            OfType(Of DataRowView)().
            Select(Function(drv) drv.Row).
            ToArray
    End Get

However, this style of code makes some of our developers uncomfortable and so our lead rewrote it to the more familiar:

Public Property SelectedRows() As DataRow() Implements IDataSourceControl.SelectedRows
    Get
        Dim plstRows As New List(Of DataRow)
        For Each bugrLoop As Infragistics.Win.UltraWinGrid.UltraGridRow In Me.ugrBase.Selected.Rows
            If bugrLoop.ListObject IsNot Nothing Then
                plstRows.Add(CType(bugrLoop.ListObject, DataRowView).Row)
            End If
        Next
        Return plstRows.ToArray()
    End Get
Mario T. Lanza
  • 1,700
  • 1
  • 13
  • 22
  • I like functional programming, but from a quick look at the code I would prefer the “imperative” (I call *declarative*) approach. It is much easier for me to read — granted this could be my experience and being a product of my environment. That said, from a quick 5 seconds I can see the prep steps and what’s being returned. I can see there’s a loop and know that adjustments to that data would more than likely happen within it. I don’t have to track down function definitions; it’s there, it’s simple. But FP is cleaner and once past the learning curve, would probably be just as quick to code. – vol7ron Feb 03 '18 at 16:49
  • It’s the learning curve that is the issue, especially when working with people that only know “just enough”of many languages. If specializing in any particular language I’m sure FP would be a better first-attempt. Then if there were inefficiencies (unit test performance), one could be more explicit in their implementations. – vol7ron Feb 03 '18 at 16:51

1 Answers1

11

Functional programming is just too complicated for inexperienced programmers. One of the illustrations is this one, where students declared that 30-LOC mess was easier and more intuitive to understand compared to the four lines FP analog.

(This is the original version of the FP example, as the answer in the link has been more recently edited to make it slightly easier to read.)

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)));

Functional programming requires a different way of thinking about the way we code and the way this code is executed. This is rarely the way the students are told in college, and once bad habits taken, it's difficult to change them.

Functional programming has also its own specific features which may appear risky in hands of beginners. Lazy evaluation is one of them, and it may take months before one starts to understand why lazy evaluation is an excellent feature, and not an annoyance.

That's also why so many beginners start programming with languages such as PHP and not languages like Haskell.

Arseni Mourzenko
  • 134,780
  • 31
  • 343
  • 513
  • 8
    I've had the opposite experience at a university where Scheme is used for the intro course. When students had to learn Java or C# most complained that Scheme was more readable – daniel gratzer Sep 01 '13 at 13:23
  • 2
    That proves my point. Students who learnt imperative programming and OOP for years would find it more readable. People who started with FP will find it more readable compared to imperative programming. Would be interesting to know what happens with students who know equally well FP and non-FP paradigms. – Arseni Mourzenko Sep 01 '13 at 13:42
  • That would be interesting, perhaps teaching a language like Common Lisp or Scala.. though neither of those are terribly beginner friendly – daniel gratzer Sep 02 '13 at 03:44
  • 1
    The main problem is that functional languages abstract to much. When a Haskeller tells you that you ran out of memory because you accumulated unevaluated thunks then there is definitely something wrong. A lot of algorithms are not efficient when they are written in a functional style. You can't implement a fast Quicksort impl. in idiomatic Haskell. Every in-place algorithm ends up in doing IO arrays in order to get good performance. Functional languages are for language purists, imperative languages are for people who wants to get thinks done in time. – Kr0e Mar 29 '14 at 19:10
  • 3
    @Kr0e: the “abstracts too much” argument against a language or a paradigm always looks strange to me. The same argument was used against all (or most) languages; hopefully, most software is not written in Assembler today. – Arseni Mourzenko Mar 29 '14 at 19:43
  • 1
    @MainMa: Well, you are right about assembler. Assembler uses the CPU registers and every C user is happy that those things are abstracted. But an abstraction should unify different things. Functional languages like Haskell are, in my opinion, too abstract. The biggest problem is that Haskellers think that state is bad, so everything is immutable. They say that this helps multithreading, but in real world, you can only represent a fracture of the common problems as an immutable-multithread problem. Functional languages are nice for dealing with datasets though. – Kr0e Mar 29 '14 at 20:00
  • 1
    The question was: Why is imperative programming preferred, and indeed it is. I think it is preferred because you can describe problems naturally (humans think in steps, believe me, it's way easier to teach imperative languages) instead of solving a problem recursively like a mathematician. It's not bad but it's a corner case. A truly pure language wouldn't do anything useful. You really need all those dirty IO stuff. And in real world everything could break. For me, functional languages are like logical languages (prolog): They have their use cases but it make everyday programming more complex – Kr0e Mar 29 '14 at 20:05
  • 6
    "Functional languages are for language purists, imperative languages are for people who wants to get thinks done in time.": According to my experience this is not true. I can get things done more quickly using functional languages. Imperative style is much more verbose and less declarative and when I have to use an imperative language I definitely need more iterations before I get things right. – Giorgio Nov 19 '14 at 21:34
  • 1
    _Any_ kind of programming is too complicated if you are inexperienced. The experience teach you how to think and if you start in a CPU-oriented world (like the C languages or assembly) you don't get the mindset needed for functional programming. It is similar to being an experience right side driver and suddenly having to drive on the left. In a left side car. Everything is cumbersome even though you can do exactly the same as you are used to. – Thorbjørn Ravn Andersen Jul 07 '17 at 15:44