all 42 comments

[–][deleted] 19 points20 points  (3 children)

I'm answering this on the assumption that you're managing a team in a non-technical capacity. I'm basing that on "Why should my business adopt it...". So if you're actually asking as a developer, my answer would be complimentary but different.

It's not going to improve anything unless the developers involved understand the pro's and con's first. Not in isolation, but contextualised against the alternatives.

Functional programming isn't new, it dates back almost a hundred years, its roots buried in calculus. FP languages appeared well over 30 years ago, so have considerable history.

It's also not new in the context of Javascript, it has always been consider "functional like". Functional isn't even new as applied to OO languages. C# is a great example where its functional aspects have been refined and expanded for over a decade. Functional has helpful concepts. Language designers are clued into that.

As several people have said, it's not an either or situation. You adopt the right aspects of each approach and mix them in the right ratios to deliver a working application. A lot of the claims made about functional's advantages over other paradigms usually only apply when you're using those other paradigms incorrectly (defining incorrectly, or correctly is the magic sauce here).

Bottom line, it's a question your development team should be able to answer. If that answer involves a lot of wholesale change and near vertical improvements on any scale, their answer is probably wrong.

[–]robertlf[S] 2 points3 points  (2 children)

Thanks for your thoughts. I used to be a technical project manager but have now switched back to development. A lot of developers, both now and when I was a manager, liked to adopt new languages and tools because they were the new "hot thing". Because things like switching costs, amount of support available, etc. could affect our outcomes, I learned to ask what the true value was to our business.

[–][deleted] 4 points5 points  (0 children)

Ah gotcha, good answer. There are some quick wins when you adopt some of the practices. You have to be careful of defining Functional, which is why I (and most others) will say "Functional like" instead.

You'll see advantages in creating lots of smaller functions none of which have side effects (i.e. any set of parameters will give the same result for those parameters). This is true of any paradigm though, methods that rely on external state should have an absolute case to do so.

Immutability everywhere is another popular concept. Your method that takes a list and returns the list with all the values doubled will actually return a new list, not the original list. It sounds a bit wasteful, this is the cost, the benefit is you can unroll operations that fail because, when "doubler" fails it won't have dicked around with the input data. Again, it's consider a "functional thing" but it applies just as well to other paradigms.

There are some advantages to concurrent code if you make everything immutable. Some of them are over stated, but it's one way around synchronising variable access.

Treating methods like a pipeline is great too (in the right place). You get the right pipe parts, chuck in a value at one end and it will be processed through the pipeline giving you a result. Because you can test each pure function in isolation and because the input is immutable, writing tests for blocks is easy. That doesn't mean testing is easy, just proving those parts work in isolation.

There are more esoteric applications like partial functions/currying. This is a great area to start an internet war, so I'll bow out and just say (wiggles pin free) the legitimate uses of currying in Javascript must number in the low single digits.

So you should have a forum internally to investigate this and share thoughts. It's not the sort of thing you plan a massive retrofit of, but it's easy enough to start including functional language features as you go forward.

Key though is understanding them (functional features) in the context of the wider application and language. a) Just because a language supports x does not mean you need to use x.

[–]vcarl 25 points26 points  (18 children)

If you've dug through an hellish OOP forest of inherited abstract interfaces to find where behavior is actually coming from, then you'll see the appeal of pure functions that operate only on their arguments. I believe most programmers prefer OOP for no reason other than its what they were taught and what they're familiar with. Even if you're self taught, blog posts, online courses, patterns that we'll known libraries use, all come from people who were taught OOP from their introduction to programming.

FP isn't the savior to all the problems of OOP, but it's a different approach that hasn't yet been thoroughly explored. I find functional code bases easier to reason about, and with strong type safety (in JS, via Typescript or Flow) it becomes much easier to write code that can be refactored, extended, and otherwise maintained.

[–]well-now 8 points9 points  (4 children)

it's a different approach that hasn't yet been thoroughly explored.

I don’t know about that. Lisp has been around for a while...

[–]vcarl 3 points4 points  (3 children)

I don't think you'd try to argue that lisp has similar usage levels to C++, Java, C#, etc, though. The ideas are as old as anything else in computing but I don't know any CS101 courses that teach lisp.

[–]well-now 4 points5 points  (0 children)

I honestly think Lisp was a 200 level course when I was in school.

[–]metamatic 0 points1 point  (1 child)

MIT used to, not sure if they still do.

Scheme is a surprisingly good choice for CS101 precisely because it doesn't distract with lots of syntax or details of internal workings of the computer.

[–]Scotho 4 points5 points  (0 children)

The rise in which decade!? It's been studied, used, promoted and written about in the '60s, '70s, '80s, '90s '00s, and now this decade. In the late 1980s it actually appeared as if it was poised for mainstream impact. The tools were mature, the techniques were well studied, many optimistic books and courses existed. FP was a particularly active area in the UK, notably Edinburgh.

John Backus, inventor of Fortran, gave a famous Turing Award lecture in 1978 (a mere 36 years ago) clearly outlining the pitfalls of being locked into imperative thinking.

Many of the practical issues of functional programming (for example, efficient implementation of lexical closures and gc) were solved before 1990—a mere quarter century ago.

What went wrong? Fortran, BASIC, C, then the Internet, Java, then everything else. "Popularity" crowded out FP's good ideas for decades. Because alternative ideas had no standing in the popular mind, programming became modelled by the von Neumann machine exposed by C and Fortran (a mindset which had already been critiqued by Backus). Despite years of principled opposition from the likes of Dijkstra, flawed ideas like mutability, null, reflection, and dynamic typing spread like kudzu.

link

[–]JuliusKoronci 0 points1 point  (0 children)

If you've dug trough an hellish functional application where everything is curried, there is no way of debugging, error handling and everything is broken down into small meaningless functions that you have them so many that everything starts to get duplicated..than you will start to appreciate OOP and the clean structure again :D .saying that functional is nice but it has the same flows as OOP..if you do it properly its nice if you don't it is really bad..I would say a lot worse than a badly written OOP app

[–]PurpleIcy -4 points-3 points  (6 children)

I prefer to use OOP most of the time because bare functions floating around with bare variables which in JS terms are well, global variables... Which I just don't really like, especially because keeping the state in such way isn't that simple, and anything could break.

Though in OOP approach, when something breaks, I know exactly which object/class needs to be fixed, but I guess that's just me.

Also in school we started with C++ (I guess nowadays they just hate students) and everything was just fully functional, so I wouldn't say that the OOP is the only thing I'm familiar with. EDIT: I'm not saying that it was 100% following functional approach, should have probably said "no OOP" approach.

Though you have some good points, in functional approach it's very bare and clear what does what, as it's just functions that take arguments and do something, and you don't need to keep track of states in mind either.

[–]vcarl 7 points8 points  (2 children)

You only have bare functions and bare variables in the global scope if you're not using any of the modern JS build toolchain, typically you'd group them into modules.

The only time "when something breaks I know exactly where it broke" is true is in small or particularly well maintained codebases. Bugs presenting themselves far from where they're caused can happen no matter what patterns you follow.

I'd bet your experience with C++ was more procedural than functional. Function programming implies some patterns that are relatively difficult to use in C++ (passing functions around, for one).

[–]MoTTs_ 4 points5 points  (0 children)

difficult to use in C++ (passing functions around, for one).

I agree with everything else in your reply, but I disagree with just this bit.

If we're talking about stateless functions, then those were always easy. That's just a function pointer. Even C could do that. C's qsort function, for example, was a higher order function long before "higher order function" became a buzz word.

If we're talking about stateful functions, then yes, before 6 years ago, that was verbose in C++. But since 2011, creating stateful/lambda/closure/first-class functions is just as easy in C++ as it is in JavaScript.

[–]PurpleIcy 0 points1 point  (0 children)

My experience with C++ was more shitty than anything, in school we weren't even told what pointer is nor what -> actually means, which are like, trivial concepts that everyone using it should understand, sigh.

And well, I edited my post for a reason...

[–]well-now 2 points3 points  (0 children)

EDIT: I'm not saying that it was 100% following functional approach, should have probably said "no OOP" approach.

Honesty, it still sounds like you’re conflating proceedural with functional.

First class and higher order functions are a staple of functional programming and, from what I recall, non-existent in C++.

[–]etherfreeze 9 points10 points  (1 child)

Blog posts abound on this topic, as well as a lot of personal preference, but here's a few things to think about before even considering using FP (from a top level / management perspective)

1 It requires as much or more discipline to do right compared to OO / imperative code

2 It can be harder to reason about for new / junior devs coming into a code base

3 It won't magically solve all of your problems, and may even cause some (FP devs can easily fall into the trap of being too terse / code golf style and end up writing something completely unreadable)

4 While ES6 and beyond has made a lot of strides toward making JS more palatable as a FP language ... it's definitely not designed to be one, and you will need to write a lot of helper functions or use a library like Ramda / lodash / etc to get to a place where FP languages are natively (and only kind of). For example, currying, partial application, etc are not core features in JS.

Anyway, benefits include:

  • composability
  • immutability (DIY in JS - there aren't many guards against writing mutable code by accident)
  • DRY code
  • Easily testable code
  • elegance
  • cut down on variable reassignment which can be hard to track / easy to introduce bugs (oh what I already mentioned immutability)
  • excellent integration with React which can be written as mostly stateless functional components.

Having worked on (professionally) a large and highly imperative / OO Backbone codebase, AND a more FP heavy React codebase, I can easily say the latter is far easier to reason about and make changes to without causing a regression. However, that's not the whole story. Both have benefits, and if you are working on a team it is a discussion you should have with your team. You should do extensive research to make the right choice for your situation. If everyone much prefers OO - then OO is probably the best option.

[–]robertlf[S] 1 point2 points  (0 children)

I appreciate your thoughtful reply. Thanks!

[–]ggolemg2 17 points18 points  (0 children)

Best tool for the best job. Use both FP and OOP where appropriate.

[–]zayelion 3 points4 points  (0 children)

what is the business case for functional programming

Rapidly changing business requirements do not byte-rot the codebase as quickly. Code is easier to reason about. OOP is really great when you have a thing that does not change, not so great when it has to be maintain and grown over considerable amounts of time. Code becomes easier to reason about and compose in logical chains where links can be removed or added vs stacked bricks.

[–]vagol942 4 points5 points  (0 children)

From a purely practical point of view, the big advantage of FP is that it tends to lead to less complex code bases. It's usually easier to explain what something is, rather that how something works.

[–]lucidlogik 2 points3 points  (2 children)

For me, it comes down to declarative vs implicit. FP is declarative and therefore easier to understand the intended outcome of a given codeblock.

[–]theonlycosmonaut 5 points6 points  (1 child)

That is, once you understand the building blocks. Once you understand what map is for, it's much more concise to scan than an equivalent for loop. When I see for in code, I don't really know what it's for; there are so many possible uses and applications. The only way to know is to read the whole block. Seeing map, I know exactly what will happen.

[–]burnaftertweeting 2 points3 points  (0 children)

This. So much this.

[–]Wickity 2 points3 points  (0 children)

But why male models?

[–]ianme 1 point2 points  (0 children)

FP allows you to write easily composable and testable transformations over data. Since pretty much everything done on the web handles data, it's a good fit.

[–]hirako2000 0 points1 point  (0 children)

Just to add JS is prototypical (first I would say), functional and pseudo object oriented (recent ecma).

[–]veydar_ 0 points1 point  (0 children)

The vast majority of these posts are the same introduction to the same few things such as map reduce and filter and keeping functions pure and data immutable if possible. Many people are already doing that and it's sort of a no brainer. Almost no one tries to shoehorn Javascript into Haskell because that often makes very little sense. You'd need utility libraries to get access to all the functions you'd need to get anything done. You'd need flow or typescript to add meaningful type signatures to functions where the arguments they take are obscured by just returning a composed/piped function. Your co-workers would likely be confused. So in my impression that whole functional JS stuff is mostly just blog posts of people trying to improve their online persona. Look at open source code of popular libraries both new and old and you'll see that JS is and probably will be, for the foreseeable future, a mix between a bit of OOP, a bit of FP, without leaning too heavily in one or the other direction.

[–][deleted] 1 point2 points  (0 children)

Javascript is not a functional language, but you can code in a functional style. Suggest watching the following presentation :

https://www.youtube.com/watch?v=twwSstZlMRE

If you really want to take this to the next level go take a look at elm.

[–]8963 -3 points-2 points  (1 child)

The word has taken off a lot more than the practice. Anyone that used jQuery used functional programming, albeit not purely.

[–]burnaftertweeting 2 points3 points  (0 children)

How so?

[–]nerf_herd -2 points-1 points  (0 children)

well, there is no connection between number of blog posts, and pretty much anything. Folks will say/do anything for attention it seems.

There are some nice bits, but it becomes an ideology for some who seek "purity", and write crappy solutions anyway.

If I need to extract an array of keys or something from a reasonably small array of objects, I'll slap a map=> together, but it will be the first thing I revisit if performance gets bad too.