DEV Community

Cover image for Deep Dive into Functional Programming in Javascript

Deep Dive into Functional Programming in Javascript

Alex Merced on April 20, 2024

Subscribe to My Coding Youtube Channel Subscribe to my Data Youtube Channel Functional programming (FP) has gained significant traction in the wo...
Collapse
 
oculus42 profile image
Samuel Rouse • Edited

Thanks for a great article!

I have encountered some pushback against the idea of Functional Programming in JavaScript, and it's good to see more discussion on the topic.

In addition to spread syntax, the structuredClone function was added to provide a simple way to perform deep cloning!

One formatting note: it seems you are missing a line break for the heading "Drawbacks" in Memoization

Easy to implement with higher-order functions. #### Drawbacks:

Collapse
 
pengeszikra profile image
Peter Vivo

Thx, I always forget structuredClone! Rare ocassion to need deep cloning, but at that time this is very handy

Collapse
 
joefiorini profile image
Joe Fiorini

I did not know about structuceredClone. Do you mean I can stop using libraries for mergeDeep? Yay!

Collapse
 
warwizard profile image
War Wizard

While I do love programmers embracing functional programming more and more... I'd rather they use functional programming languages to learn about it than try to Frankenstein functional programming concepts into other languages. No matter how well intended this is, it always leads to misunderstandings.

There's a lot to talk about here, and I might miss stuff and probably go about it not in a very orderly fashion, so bear with me.

There are no "pure functions" in functional programming, these only exist in procedural programming to describe functions that return the same result for the same input without any side effects. All functions in functional programming are mathematical functions, they describe a one directional relationship between two sets of values, the input and the output. "But, isn't that the same?" - NO, procedural "functions" are still procedures, they are not really functions in the mathematical sense, and while they don't cause any intended side effect, they might cause unintended side effects as they still work directly on memory data and references to memory data, and further processing on returned data might cause side effects if handled improperly by subsequent procedures.

Immutability has different meanings whether you are using a procedural language or a functional one, because "variable" means something different in each language. In procedural a variable is a value stored in memory, and it's called as such cause the value might change during the execution of a procedure. In functional a variable is the input of a function (or a value derived from it), it's called as such cause its value can be any within the input set (the domain of the function), but during the evaluation of a function that value doesn't change, that's what we refer as immutability in functional. In contrast, immutability in procedural means the procedure doesn't (or cannot) change the value stored in memory. Therefore I will refer from here on to immutability in procedural as "state immutability".

Now that both these clarifications are out of the way... neither pure functions nor state immutability are "features" of functional programming, rather they are concepts mistranslated from the fundamentals of functional programming. It's just procedural programmers trying to mimic functional within procedural languages [ insert here "Look What They Need to Mimic a Fraction of Our Power" meme ].

Functional programming is a completely different paradigm, programs are described as mathematical functions, and this means procedural programmers have to throw everything they knew about programming and start thinking differently. There is no control flow (*) in functional, there are no for loops and the if is just the ?: operator.

(*) the savvy reader might say here "but what about monads?"... well, monads, and more specifically all the syntactic sugar usually associated with them, might give us a bit of procedural looking constructs within functional... think of the meme mentioned before but in reverse. Each paradigm has its pros and cons, but that hasn't stop programmers from trying to mix them in usually not very good ways.

A bit of tangent here but since it was mentioned as a possible benefit the "testability", or easier testing of code written in a functional fashion... well... there is no need to test in functional programming. Let me rephrase that... in functional we don't test, we prove. This is one the best things about the paradigm, it's all just math, so it's more straightforward to write formal proofs, and proofs are better than tests as they validate every possible input. Of course, formal proofs are possible for procedurally defined algorithms but they are so much more cumbersome.

Memoization is not an optimization technique per se, it's only such in very specific scenarios (when using certain recursive functions and/or data structures), and the wrong idea that it works in a general sense has become one of the recurring myths going around, and common cause of unnecessary memory hogging. The proper optimization technique is Dynamic Programming, which is not a specific algorithm but an algorithmic designing technique.

Then... Monads... Why is it always monads? This is probably the most misunderstood topic in all computer sciences, and I dare not say I fully understand them either but I'm confident almost everything said here about monads is wrong or inaccurate. Monads are a math construct, polymorphic types that wrap another type and provide specific operators that follow formally defined laws (which are not the ones described here). They are particularly used to abstract state machines in functional languages and usually using some syntactic sugar that help define monadic operations in a seemingly procedural manner, but this is not their only purpose.

Furthermore, monads make no sense within a procedural paradigm. They are the kind of math used to abstract a procedurally defined algorithm to make formal arguments about it. Having explicitly monad-like constructs in a procedural setting seems redundant/contradictory. Things like Javascript's Promises might seem monadic but strictly speaking, they are not. A "true" monad is not the state of a program, but the "program" itself, meaning, in a functional setting, whenever you evaluate a monad, you are effectively running the program it represents.

I want to remark that I don't mean to demean the value of the techniques and methods shown here, on their own they have their merits (except the whole stuff about monads, stay away from that, for your own sanity sake), just that this really has nothing to do with functional programming, it might be inspired by functional programming but it's not the same by a wide margin.

And there's already ways to combine functional and procedural in a sane way. Programmers seem to forget that you don't have to write your entire solution in only one language. Libraries can be built in one and then used in another. If I remember correctly there are ways to compile functional code into WebAssembly, at least for Haskell. Or if you are targeting NodeJS you can just go native.

Collapse
 
juanfrank77 profile image
Juan F Gonzalez

Functional programming is quite a beauty. Few years ago I started learning a bit about it. It's quite challenging to grasp it at first (coming from an imperative paradigm) but then it's like seeing in a different way.

This article is a great primer for folks here to dive deeper into this style and maybe who knows, they'd like to try Haskell (that's kind of what I did 😅)

Collapse
 
joefiorini profile image
Joe Fiorini

This is a good article and a great explanation of monads, although they do not always need to be objects using method-chaining. One of the best examples of a monad-like concept is widespread use in the reducer/state model made popular by Elm and brought to JavaScript by Redux (now built into React with useReducer). Anytime you assign a value to a property on this in an object you are creating a side effect.

Using a separate, pure function to handle state simplifies the rest of the code so much! It also allows you to create additional pure, memoized functions to retrieve values from the state. The reselect library for Redux is a great example of this.

Collapse
 
eshimischi profile image
eshimischi
Collapse
 
joefiorini profile image
Joe Fiorini

I used fp-ts on a project pretty heavily. It's a great library but it does have quite a steep learning curve. If you pointed a team member to the docs I guarantee their eyes would gloss over at the first use of the word "homomorphism".

Collapse
 
eshimischi profile image
eshimischi

This project isn’t new, at least it shows pros and cons of using FP in TS/JS, further is only your choice whether to use or not

Collapse
 
jderochervlk profile image
Josh Derocher-Vlk

This library changed my life. It makes working with typescript tolerable.

Collapse
 
nandigama015 profile image
Sai

I am new to javascript, Please let me know if I am thinking wrong. Since validateInput function return true for the last example, the output would have user details with name set to true rather than John Doe.

Collapse
 
tohodo profile image
Tommy

While I appreciate the novelty, IMHO it's not pleasant to do FP in JavaScript. I'd rather go all in on Elm (check it out, it is superb).

Collapse
 
joefiorini profile image
Joe Fiorini

After having tried and failed multiple times to bring Elm into teams that argument highly depends on a lot of things nicely lining up. Don't get me wrong, Elm is a great language and is a large part of why we're even having this conversation right now!

There is a lot of value in meeting people where they are. 99% (made up but probably accurate) of frontend codebases use either JavaScript or TypeScript. Functional programming is superior to OOP (let's just take that as a fact, k? 😉). JavaScript has a lot of features that allow us to write functional-style code (I spent an entire year building React apps without creating a single class, save a couple error boundaries). Let's throw out the bathwater but keep the baby.

Collapse
 
jderochervlk profile image
Josh Derocher-Vlk

I've also tried to pitch Elm. It's a tough sell since it's an entire ecosystem and framework.

The past few years I've been using ReScript and started introducing it at work into a couple projects, and it's much easier to get people on board since it works with React and JSX and doesn't have its own package manager.

Collapse
 
tohodo profile image
Tommy

You're preaching to the choir 🙂 youtube.com/watch?v=oYk8CKH7OhE

Collapse
 
starck profile image
Starck Rock

This deep dive into functional programming in JavaScript is a treasure trove for both beginners and seasoned developers alike! The clarity of explanations and the practical examples provided truly demystify the concepts of functional programming, making it accessible to all. I particularly appreciated how the article seamlessly blends theory with real-world application, as I also took online class help for this before.

Collapse
 
armstrong2035 profile image
Armstrong Olusoji

I have a feeling that currying may reduce my dependence on Async/Await ...

Collapse
 
patroza profile image
Patrick Roza

Promise not a monad

Collapse
 
jderochervlk profile image
Josh Derocher-Vlk

If you squint at it it's kinda Monad like. It's like explaining to an alien that a cat is a type of small dog lol.

Collapse
 
krakoss profile image
krakoss

great article

Collapse
 
jetmal_singh_17c6ba2af784 profile image
Jetmal Singh

The content of this blog is very interesting and informative. Want more blogs of this kind. Thank you Care Services in Austin!

Collapse
 
jetmal_singh_17c6ba2af784 profile image
Jetmal Singh

Thank you for sharing this for bookworms Engaging Video Content!