DEV Community

Cover image for JavaScript and Functional Programming: A Dive into Pure Functions, Currying, and Functional Composition
Jaimal Dullat
Jaimal Dullat

Posted on • Originally published at Medium

JavaScript and Functional Programming: A Dive into Pure Functions, Currying, and Functional Composition

Have you ever felt the thrill of discovering a new way to approach problems in your coding journey? Or the satisfaction of writing code that’s not just functional, but also elegant and efficient? If you’re nodding along, or even if you’re just curious, you’re in for a treat. Today, we’re embarking on a delightful exploration into the realm of functional programming in JavaScript.

Whether you’re a seasoned developer or a curious newbie, this guide on pure functions, currying, and functional composition promises to sprinkle a touch of magic on your JavaScript endeavors. So, grab your favorite beverage, get comfy, and let’s dive deep into the mesmerizing world of functional programming!


What is Functional Programming?

Functional Programming (FP) is like giving someone a set of instructions to follow, step by step, without any distractions or deviations.

Imagine you have a toy robot. You give it a set of commands like “move forward”, “turn left”, or “pick up”. Every time you give it the same command, it does the exact same thing. It doesn’t suddenly decide to dance or sing; it just follows your instructions precisely.

In FP, our code is like that robot. We write functions (sets of instructions) that:

  1. Always do the same thing with the same input. If you tell it to add 2 and 3, it will always give you 5. It won’t suddenly give you 6 or 4.

  2. They don’t have memories of their own. They don’t remember past actions or results. Every time you run them, it’s like they’re doing their task for the first time.

  3. Don’t mess with other stuff. They mind their own business. If a function’s job is to calculate something, it won’t secretly change something else in your program.

This way of coding makes it easier to predict what your program will do, find mistakes, and understand how different parts of your program work together. It’s like having a well-trained robot that always follows your commands without any surprises!


1. Pure Functions

A cornerstone of functional programming, pure functions have two main characteristics:

  • Deterministic: For a given input, a pure function will always produce the same output.

  • No Side Effects: A pure function does not cause any observable changes outside its scope. This means it doesn’t modify any external variables, log to the console, or perform any other side effects.

Benefits:

  • Predictability: Since the output is solely determined by its input, testing and debugging become much easier.

  • Reusability: Pure functions can be safely reused in different parts of your application without unintended consequences.

Example:

function add(a, b) {
  return a + b;
}
Enter fullscreen mode Exit fullscreen mode

The add function is pure because for the same values of a and b, it will always return the same result, and it doesn't modify any external state.

For example, if you give it the numbers 2 and 3 to add, it will always return 5.


2. Currying

Currying is about breaking a function that takes multiple inputs into a series of functions that take one input at a time.

Currying is like breaking down a multi-step task into smaller tasks that you do one at a time.

Imagine you have a machine that makes colored stickers. Normally, you’d tell it both the shape and color at once, like “Make a blue star.” But with currying, you’d first tell it “Prepare to make a star,” and then, “Now, color it blue.”

In JavaScript, instead of a function that takes two inputs at once:

function makeSticker(shape, color) {
  return color + ' ' + shape;
}
Enter fullscreen mode Exit fullscreen mode

With currying, you break it down:

function makeSticker(shape) {
  return function(color) {
    return color + ' ' + shape;
  }
}
Enter fullscreen mode Exit fullscreen mode

Now, you can first set the shape:

const starSticker = makeSticker('star');

And later, set the color:

const blueStar = starSticker('blue');  // This gives you "blue star"
const redStar = starSticker('red');  // This gives you "red star"
Enter fullscreen mode Exit fullscreen mode

Benefits:

  1. Partial Application: Currying allows you to fix a certain number of arguments for a function, creating a new function. This can be useful when you have functions where some arguments remain constant throughout the application.

  2. Enhanced Function Composition: Currying can make it easier to compose functions. When functions are curried, you can easily chain them together, leading to more readable and maintainable code.

  3. Increased Modularity: By breaking down functions into unary functions (functions that take one argument), you can reuse and combine them in various ways, leading to more modular and DRY (Don’t Repeat Yourself) code.

  4. Laziness: Curried functions support lazy evaluation. This means you can delay the evaluation of the function until all its arguments are available.

  5. Improved Code Clarity: When functions are curried, it can make the intention of the code clearer. Each step or function call becomes a descriptive action, making the code more self-documenting.

  6. Flexibility: Currying provides flexibility in the order of supplying arguments. You can provide arguments to a function in any sequence, and it will return a new function waiting for the remaining arguments.


3. Functional Composition

Functional composition is the process of combining two or more functions to produce a new function. It’s like a pipeline where the output of one function becomes the input of the next.

Example:

function double(x) {
  return x * 2;
}

function increment(x) {
  return x + 1;
}

const doubleThenIncrement = x => increment(double(x));

doubleThenIncrement(5);  // Returns 11
Enter fullscreen mode Exit fullscreen mode

Benefits:

  • Readability: Instead of nested function calls, you have a clear sequence of data transformations.

  • Modularity: You can easily rearrange, add, or remove steps in the pipeline.

Difference between Currying and Functional Composition?

Imagine you’re getting ready for a party.

  1. Currying is like choosing your outfit piece by piece. First, you pick a shirt, then pants, then shoes, and so on. You’re breaking down the process of getting dressed into smaller steps, and you handle one step at a time.

  2. Functional Composition is like combining different activities to get ready. For example, first, you take a shower, then you get dressed, and finally, you put on some perfume. Here, you’re combining different activities (or functions) to complete the whole process of getting ready.

In terms of coding:

  1. Currying:

    • It’s about breaking a function that takes multiple arguments into a series of functions that each take one argument.
    • Example: Instead of a function dress(shirt, pants), you'd have a function dress(shirt) that returns another function to pick pants.
  2. Functional Composition:

    • It’s about combining two or more functions to create a new function.
    • Example: If you have a function shower() and another function dress(), you can combine them into a new function getReady() that does both.

In essence:

  • Currying is about how a single function receives its arguments.

  • Functional Composition is about how multiple functions are combined together.

Both are powerful concepts in functional programming, but they address different aspects of how functions are structured and used.

Conclusion

Functional programming offers a fresh perspective on solving problems and organizing code. By embracing concepts like pure functions, currying, and functional composition, JavaScript developers can write more robust and maintainable applications. While it might seem daunting at first, the benefits in terms of code quality and predictability are well worth the effort. So, the next time you sit down to code, consider giving functional programming in JavaScript a try!

🔗 Connect with me on:

A Big Thank You! 🌟

  • Readers: Grateful for every click and read.
  • Engagers: Claps, comments, shares — you’re the best!
  • Followers: Honored by your continuous support.
  • Silent Admirers: Your presence doesn’t go unnoticed.
  • Constructive Critics: Your insights help us improve. 💌 Stay connected and thanks for being part of our journey.

Top comments (0)