
Functional Programming Is Not Popular Because It Is Weird - brakmic
http://probablydance.com/2016/02/27/functional-programming-is-not-popular-because-it-is-weird/
======
chriswarbo
There are many styles of functional programming; the thing they have in common
is that they all use first-class, high-level functions to implement features
which other languages might implement via special-purpose syntax, bytecode,
compiler passes, etc.

The "lambda the ultimate" papers are the classic example of using functions to
implement a variety of language features, including jumps. Hence the author's
claim that functional programming is an "inside-out" approach is more of a
question of style than of paradigm.

For example, even simple function composition can approach the clarity of
imperative code for following a step-by-step process. The result tends to look
like UNIX pipes, although traditionally they're read "right to left" (but you
can trivially define your own composition function which goes the other way).

Here's an example of the author's task, written in a compositional style
rather than an "inside out" style:

    
    
        heatedOven = preheat 175 oven
    
        preparedPans = grease . flour $ pans
    
        flourMixture = whisk . add flour . add bakingSoda . add salt $ smallBowl
    
        creamedMixture = until (all [light, fluffy]) . cream . add butter . add whiteSugar . add brownSugar $ largeBowl
    
        bananaMixture = mix . add bananas . repeat eggCount (beat . add egg) $ creamedMixture
    
        batter = stir . add (chop walnuts) . repeat (size / spoonful) (add (spoonful flourMixture) . add (spoonful buttermilk)) $ bananaMixture
    
        baked = take . wait 30 . add (add batter preparedPans) $ heatedOven
    
        cake = take . wait 10 . add baked $ dampen teaTowel

~~~
greydius
If you create a Kitchen monad, you could write it imperatively. Then you can
have your functional cake and eat it too. (I couldn't stop myself.)

~~~
tmptmp
a "kitchen monad" may seem to be a overkill for doing what you (or your mom)
may need to bake a small number of cakes for you to consume

but

bakery monads are what is needed if you want to bake hundreds of thousands of
cakes of hundreds of different variations (types) in a manageable manner.

FP starts to make (more and obvious) sense there not in the small household
kitchen. But even then that is not to say that FP doesn't make sense in a
small household kitchen. Only, it is very difficult to make sense of that
sense at the smaller scales.

~~~
greydius
I was just attempting to inject a little humor into the situation while
bringing attention to the fact functional and imperative are not necessarily
mutually exclusive. In fact, I'm of the opinion that Haskell is the best
imperative programming language. It's just really hard to explain why that is
the case when the popular sentiment is that monads are scary and impossible to
understand. In any case, these threads always devolve into ideological
bickering which I try to avoid.

------
jonahx
The author's attempt to rewrite the cake recipe in a functional style
misunderstands the paradigm completely.

The correct image here is all the stuff -- oven, pans, butter, flour, salt,
etc -- entering a funnel on the left and producing a baked cake on the right.
The funnel itself, if you were to peer inside it, would be composed of
multiple sub-funnels: pans with batter + oven as the last step, empty pans and
bowls of batter as the step before that, and so on.

It's natural, not weird. The metaphor is used all the time on cooking shows,
where they show you bowls of all the ingredients, and the final product next
to them.

~~~
braythwayt
It’s easy to imagine the funnel you describe, if we imagine we are building a
factory for cakes. Naturally, the ingredients arrive on various conveyor belts
or in pipes, are mixed, and cakes emerge from the other end.

------
braythwayt
The author says that when they imagine what they want to tell the computer,
they imagine an imperative sequence of commands and side-effects. Lo and
behold, an imperative language is a closer match to what they are thinking
than a functional language.

No. Shit. Sherlock.

I’d say the same thing about human languages. Can you imagine me criticizing
Japanese because when I try to translate the English in my head to Japanese on
a word-for-word basis, it’s a lot of hard work and the result is terrible?

The point of learning a different language is not to learn how to translate
what is in your head into whatever the language demands, it is to _change what
is in your head_. Alan Perlis put it best:

    
    
      > A language that doesn't affect the way you think about programming, is not
      > worth knowing.
    

What I would say, is that if you know language X and want to compare it to
language Y, you need to keep working at Y until it affects the way you think
about programming. If it doesn’t, you can then say that it failed to improve
you as a programmer. If it does, you can then give a thorough review of how
your new perspective has improved you, and whether it is worth the effort.

I’m not saying FP is better or worse, but I am saying that “It’s terrible for
writing the imperative programs in my head” is not a good argument.

~~~
discreteevent
In fairness he explicitly says he is trying to explain why it's not popular.
Not why it's not a gold thing to learn. He days it's a good thing to learn at
the end of the article.

The reason he says it's not popular is because the vast majority of people
think imperatively when dealing with a problem that involves state and time.
They might think functionally when trying to express an immutable law or when
categorising the qualities of a horse or whatever. But when doing something
that involves changing the state of the world in time and space (which is a
significant part of many programs) they think imperatively. And even C will
support enough of the functional stuff to do the rest (see Numerical Recipes,
for example)

~~~
braythwayt
This is true, however in most programs, the entities that map directly to
stateful entities in the “real world” are in a minority, and the bulk of the
program consists of entities that serve the program’s implementation needs.

Those can be written in any style we like. For example, in languages like
JavaScript and Ruby, if we wish to compose classes out of smaller components,
we can imperatively modify classes, or we can write functions that take
existing classes and return new classes consisting of the originals composed
with whatever additions we desire.

What I am trying to say is that while imperative may feel more natural for
problems involving state and time, we often perceive that problems require
state and time even when they don’t.

\---

I can fully accept the argument that people don’t like FP because they
_perceive_ that their problems need imperative solutions. But that is not the
exact same argument as “people don’t like FP because their problems involve
space and time."

~~~
discreteevent
OK I think that's a good and useful point and a motivator for learning FP.
Nevertheless because most people continue to perceive things imperatively and
because as the article says FP is puzzle like then the author still is
probably right when they say that FP will remain unpopular.

I like "solving puzzles" but I don't like solving them under pressure. I also
don't like deciphering someone else's puzzle when I am in a hurry and when I'm
unlikely to never need this piece of code again. So even for people who like
puzzles it's often the case that they just need to get something working fast
that's reasonably correct.

The fact that life is short and that the world changes so rapidly is what
makes worse better.

------
bunderbunder
The author does have a point. Another issue is that the problems FP solves are
problems that I think many developers genuinely don't have. Or when they do
have them, they occur in very specific ways that can easily be handled with an
80% solution bolted onto an existing imperative-first language. Node, LINQ and
Numpy all come to mind. These have the advantage of confining the weirdness to
one spot, which makes it easier for users to accept them because they don't
feel trapped the way they might in a language like Haskell or Racket.

Meanwhile, FP does introduce some of its own problems, and I think many of my
fellow FP fans are too quick to downplay them. Performance is one. It might be
solvable by compilers, but for those of us who are not likely to spend much
time hacking on the compiler for our language of choice that's a small
consolation.

The end result being, it's still the case that my adventures in functional
programming (which are generally done using a multiparadigm language like F#
or Scala) will go something like this more often than I care to admit:

    
    
      1. Implement imperative solution.
      2. Feel guilty, go back and replace it with functional one.
      3. Find performance problem. Dig out optimizer.
      4. Optimizer points to code from step 2.
      5. Revert back to version from step 1.

~~~
hcarvalhoalves
> Another issue is that the problems FP solves are problems that I think many
> developers genuinely don't have.

Here's the one billion dollar question. Which is harder?

1) Correct code

2) Fast code

~~~
nostrademons
You forgot a couple options:

3) Available code

4) Familiar code

The history of the software industry has basically been 40 years of customers
choosing code that exists, solves their problem _right now_ , and doesn't make
them think too hard about how to use it. They choose this over correct code
(hence, Microsoft) and over fast code (hence, Python/Ruby/Javascript/PHP).

FP actually helps you write _both_ fast and correct code. The problem is that
it requires a good deal more planning up-front and more effort to change
things when requirements change. This has usually been a non-starter with the
majority of customers: they want software that does what they need it to do,
right now, and will continue to do what they need it to if they change their
mind. If it screws up occasionally or makes people wait, that's okay, it's
still faster & more accurate than a human is.

------
pklausler
I've had smart people complain that they couldn't figure out how to write
simple programs in Haskell after days of honest effort. One problem, I
believe, is that functional languages encourage more of a bottom-up approach
to design, whereas many C/C++ coders naturally decompose problems in a top-
down manner. So math types, who are used to building up grand structures from
smaller propositions, find pure FP pretty congenial because they can write
smaller independent functions and attack the parts of the problem that they
know how to solve.

~~~
rntz
Anecdatally, I'm a very top-down programmer, and also a discrete math & logic
nerd, and I tend to prefer FP. I'm not sure why you think "math types" tend to
work bottom up. Perhaps we mean different things by top-down/bottom-up? Can
you give an example of what you think of as "top down" design versus "bottom
up" design, and why it seems "top down" is easier in an imperative language
and "bottom up" easier in a functional one?

~~~
pklausler
Bottom-up design is the creation of little stand-alone components that can be
understood in isolation and, when written abstractly, perhaps useful in
multiple contexts. I find that pure FP languages ease bottom-up design because
of the lack of shared mutable state and their strong support for composition.

------
dasil003
If all the programs you write are like recipes, then imperative probably makes
a lot of sense. Imperative is never a problem for small programs. It's when
they grow over time that they become more and more difficult to reason about.
In the best case you manage the complexity with good architecture, refactoring
and automated testing practices; in the worst case you end up with a program
that is not worth changing because every bug fix introduces two new bugs.
Functional programming allows breaking through that ceiling at the expense of
a good deal more rigor.

~~~
SeanDav
And yet the software industry survives and thrives with only niche use of
functional programming at best...

EDIT: To clarify. I am agreeing with the original author. If Functional
Programming is as great as it is supposed to be it would have been eating
everyone's lunch by now. It has been around forever, yet it remains quite
niche. This indicates strongly that there must be underlying reasons it is not
more popular.

~~~
dasil003
How is that a rebuttal? I feel some unspoken axe to grind...

------
makmanalp
Hah! This is amusing.

In one of my classes freshman year, one of my favourite professors (Kathi
Fisler <3) gave us an assignment where we made a silly game with an airplane
that flies around and drops things. And I remember wondering how to do that
without mutable state for the location of the plane, etc. Then I just remember
seeing in the instructions for the assignment something like:

> write a function that takes a world and returns a new, updated world with
> the plane at its next location

and I just remember sitting there with my mind completely blown. Looking back
at it, it doesn't seem as profound as I thought it was at the time, but maybe
that's just because the novelty has worn off for me and a few years in
industry have made me cynical, who knows :-)

Anyway, I think just learning to look at a problem differently I think gives
you valuable insight into it and into your mind. Doesn't matter if you end up
using it or not.

> I spend too much time trying to figure out how to say things as opposed to
> figuring out what to say.

Ha! Again, I think this is just a different approach. When I tried out
haskell, it was intriguing that the modus operandi was: "think a lot about a
problem, then write down a little code". I like that this is the opposite of
my instinct to jump in with a solution, then kinda heuristically change it to
get to code that works, and ultimately I think lead me to think a bit more and
end up with clearer problem definitions and solutions.

~~~
firebones
Does Kathi Fisler have any online coursework? Because your experience sounds
great and I'd love to be able to experience it or recreate it for my own
enlightenment.

~~~
makmanalp
It was kinda based on How To Design Programs
([http://www.htdp.org/](http://www.htdp.org/)) though to be honest I never
touched the book and relied mostly on the in class instruction (which was what
made this class awesome IMHO). I found the website for a newer version of the
class:

[http://web.cs.wpi.edu/~cs1102/a08/](http://web.cs.wpi.edu/~cs1102/a08/)

and OMG! I found the assignment!

[http://web.cs.wpi.edu/~cs1102/a08/Assignments/Hwk2/index.htm...](http://web.cs.wpi.edu/~cs1102/a08/Assignments/Hwk2/index.html)

> A function update-world that consumes a world and produces a world
> reflecting what happens when no key is pressed

OK, not phrased quite how I remember it but I guess that's where the epiphany
happened :)

I took another class with her that was programming languages, and we used
Programming Languages: Application and Interpretation
([https://cs.brown.edu/courses/cs173/2012/book/](https://cs.brown.edu/courses/cs173/2012/book/))
and the course website
([http://web.cs.wpi.edu/~cs4536/a14/](http://web.cs.wpi.edu/~cs4536/a14/))

This class also had some great epiphanies for me, but again, I think the
instruction being top notch helped keep my attention going. This is more
advanced stuff conceptually.

------
aikah
> Everyone should learn at least one functional programming language and try
> to apply what they learned in other languages. But if functional programming
> languages want to become popular, they have to be less about puzzle solving.

Because FP relies on an insane amount of theory.

Often FP aficionados are incapable of explaining functional programming
concepts to others without using FP idioms or jargon. I still don't have the
foggiest idea of what a monad or a functor is, or why the hell would I want to
use currying or partial application, when my imperative code just works
(that's not entirely true, and javascript has done a great job at popularizing
some concepts, like closures, partial applications or first class functions).

Now compare with OOP : polymorphism , inheritance and encapsulation are easy
to explain : Everybody can understand that a machine can be turned on by
pressing a button, no matter what machine it is(phone,computer,screen) :
polymorphism. It's easy to explain encapsulation : you don't need to how the
inner working of a microwave in order to use it. Same with inheritance.

I agree that one should learn at least an FP language so one is forced to deal
with a specific problem a certain way, that's good exercice. But I shouldn't
have to understand category theory in order to learn Haskell or Clojure.

~~~
nostrademons
Nah, OOP concepts like polymorphism, inheritance, and encapsulation were crazy
difficult to understand when they first came out. There were a lot of Car &
BankAccount examples that didn't really reflect how people actually use OOP in
the real world.

The thing is, all the lucrative software engineering positions created in the
late 90s required knowledge of OOP. Which meant that all the wannabe software
engineers put in the time and effort to learn it, because that was how they
could get a high-paying job. And so now you have a critical mass of people for
whom OOP is second-nature, who can explain things to junior developers when
they ask questions.

Follow the money. FP isn't popular because outside of certain niche domains
(eg. high-assurance software), it doesn't provide a competitive advantage
large enough to build billion-dollar industries off of. If knowledge of FP
suddenly started becoming necessary to get a six-figure software engineering
job, you'd see many more people putting in the effort to learn about FP
concepts. (This may already be happening with React in web development, with
Hadoop/Spark/MapReduce in big-data, and with Swift in iOS development, but
it's a new trend that'll take years to mature.)

~~~
marcosdumay
Graphical interfaces pushed OOP into the mainstream. As plain structured
programming was not powerful enough to create GUIs, people were forced to
learn it.

The fact is, for an industry that talks so much about lifelong learning and
innovation, software developers are very conservative.

------
hcarvalhoalves
If you learned that "programming is like telling the computer a recipe" I can
see how FP looks strange.

It's a bad analogy though.

[http://pages.cs.wisc.edu/~remzi/Naur.pdf](http://pages.cs.wisc.edu/~remzi/Naur.pdf)

~~~
ktRolster
It's an example of that style of thinking that made Dijkstra write his famous
quote,

"It is practically impossible to teach good programming to students that have
had a prior exposure to BASIC: as potential programmers they are mentally
mutilated beyond hope of regeneration."

------
typon
Why the heck would you write the functional recipe the way he wrote it?

1\. Take an oven and apply 175 C setting on it, producing a preheated oven.
Set this aside.

2\. Take two 8 inch round pans and some grease and flour, produce two 8 inch
round pans with grease and flour applied on them.

3\. Take a small bowl, some flour, baking soda, salt, salt and a whisk (a
first-class function), return a small bowl with flour, baking soda and salt
whisked in it.

and so on.

When you think of functional programs as series of operations chained
together, it becomes really natural. In most recipes you don't need to loop
back to an existing state.a

~~~
pekk
The real cake recipe can specify how to achieve the results instead of just
saying that they should be achieved. It does not have to deal with issues like
lazy evaluation or defining a batter monad. It does not have to trail off into
"and so on" or else go on for far too many lines because of how tortured an
exercise it is to make "pure functional" cake recipes.

If you want to argue with this, just deny that cake recipes are a good
metaphor for programming, since they are essentially imperative and that is
begging the question. But you aren't going to convince people that weirdly
abstracted cake recipes are easier to write or follow.

------
rntz
The article could use a better example. "C++ templates are complicated and
hard to write compared to straight-line imperative code" is not going to
convince any functional programmers that imperative programming is nice, even
if you can argue that C++ templates are a "functional" language.

------
pjc50
Nail on the head there. The humble state machine is a more important part of
programming than people like to admit. And a very large amount of business
logic is most naturally expressed in terms of data state manipulations, real
world state manipulations, I/O. To do I/O in FP you have to deal with monads,
which are hard to understand and work with.

(You can tell that monads are hard to work with because there are so many
articles telling you that they're easy)

The common ground is functional-ish and mostly-stateless programming ("const"
etc). C# is actually becoming very good at this, and you can always cross into
F# if you want.

~~~
moonchrome
I think you're conflating functional programming with Haskell.

You can use something like Clojure without touching monads, just use
functional data structures to represent values instead of using objects, and
the using mutable state is simple just not the default and you rarely need to
go there.

In fact if you're using something like React and something like Redux you're
going in that direction from the other side - in Clojure it's basically the
natural way to solve the problem (and frankly all of their concepts map much
better to CLJS than JS)

I feel like people pushing Haskell and all of the weirdness that comes from
lazy evaluation did more harm to FP perception in the general programmer
community than good.

~~~
justaaron
beg your pardon? you said "react cool" and "lazy eval bad" in the same
sentence... what's react but lazy eval of the dom?

~~~
moonchrome
There's nothing wrong with lazy evaluation, like lazy seq/iterable transforms
- it's just not a good "default" IMO

------
Ericson2314
The title is much better than the article. It is very different, "weird"
relative to norm, and the industry is doing well enough that there just is no
pressure to do something different.

Honestly that makes sense to me, and I don't blame programmers who are happy
with their jobs/lives/workflow/whatever from switching. But when the
mainstream idolizes "disruption" and "innovation" above all else, y'all start
looking mighty hypocritical. Please, for the sake of us functional
programmers, choose one of your revolutionary aesthetic or your shitty
languages, but not both.

------
melling
I started learning OCaml a few days ago. It doesn't seem that bad. I put my
notes into Github earlier today:

[https://github.com/melling/ComputerLanguages/blob/master/oca...](https://github.com/melling/ComputerLanguages/blob/master/ocaml.org)

I've been collecting my notes for a while on Haskell and OCaml. After reading
this article, it seemed like OCaml was a good FP choice to start with:

[http://roscidus.com/blog/blog/2014/06/06/python-to-ocaml-
ret...](http://roscidus.com/blog/blog/2014/06/06/python-to-ocaml-
retrospective/)

------
bad_user
I also learned programming with references to cooking recipes. But you know,
biggest problem is that's bullshit. First of all because people can't
translate a cooking recipe into something good without vast prior experience.
But also because cooking recipes are single threaded and fairly simple and our
current systems are anything but.

In fact I think the cooking recipe analogy does way more harm than good. And
let's be honest, there's nothing weirder than X = X + 1, being the number one
reason for why many people can't understand programming.

------
ddellacosta
There are a lot of problems with this piece, like there are always problems
with these OOP/imperative vs. FP posts.

> Both humans and machines are really good at implicit state attached to time.

That may be true for machines; they always know where all _their_ state is.
But we humans are terrible at managing state, especially implicit state,
_especially_ when we have to reason about how it changes as time passes. We
can't keep all that state in our head, and as soon as a system gets reasonably
complex even simple values mutating get hard to juggle in our puny minds. I
would venture to guess, unscientific as it may be, that a majority of bugs in
software have to do with humans not being able to reason effectively about
state.

Pure functions taking immutable data in and spitting out new values eliminate
many of the challenges with managing state. It's vastly simpler for us humans
to understand what's going on with our state when we deal with chaining
together a bunch of functions manipulating data immutably, and push managing
mutable state out to the very specific points at the edge of the system. It's
not a silver bullet--but it helps. And it's not weird at all, once you're used
to it; quite the opposite.

> Writing functional code is often backwards and can feel more like solving
> puzzles than like explaining a process to the computer.

> I'm writing this blog post because I ran into a related problem recently.
> C++ templates are accidentally a functional language.

Functional programming advocates can't even agree on a definition of what
functional programming is, and I'm even less sure what the author intends.
What they have chosen to highlight is not what I recognize as functional
programming; while I think it's good the author wants to talk about
immutability as one facet of FP, it seems pretty bizarre that they claim that
functional program often dictates you write your code backwards, or that they
choose an already implemented solution and their attempt to refactor it
functionally using C++ templates as a place to critique functional programming
in the real world.

More generally, the big problem with these articles is that they fundamentally
focus on the wrong things. Whether someone has issued a blistering indictment
of OOP and all its failures as a methodology or we get a piece like this, we
end up arguing over nonsense because we don't have a standard definition of
OOP or FP that everyone can agree on, and it's the wrong level of abstraction
to be arguing over anyways.

What we should be talking about are specific language features and what they
bring to the table, including how they interact with other language features,
how they are implemented in various environments, etc. What does immutable
data do for us? How can pure functions help us reason about our code better?
What kinds of type systems are out there, and what positives or negatives do
they have in different contexts? Does encapsulation bring anything to the
table or is it a net negative? Etc.

I'd encourage anyone considering writing yet another glib takedown of OOP or
FP to take a step back before they put text to screen and consider instead
discussing specific features that have widely agreed upon definitions and how
those programming language features lead to certain outcomes, without making a
dramatic overarching statement about the weirdness or badness of OOP or FP.
Pieces like this only further reinforce the superficial pop culture that
currently dominates our industry.

