DEV Community

Cover image for ๐Ÿ› What the heck is Currying? ft. JavaScript
Yash
Yash

Posted on • Edited on • Originally published at yashguptaz.com

๐Ÿ› What the heck is Currying? ft. JavaScript

I know that youโ€™re salivating, perhaps the dev world has become too delicious with JAMStack and now Iโ€™m talking about curry? So before you starve to death with these wonders of dev world let me introduce you to what currying is in general.

Currying was named after Haskell Curry, what currying essentially means is taking a function that takes multiple parameters and converting it into a function which only takes one parameter and returns a function which then takes the next parameter.

Currying is not JavaScript specific it is also a mathematical thing just like function (Remember good ol' f(x) ?)

// Not curried
const add = (x, y) => x + y

// Curried
const add = x => y => x + y
const addFive = add(5)
addFive(6) // 11

As you can see using Currying we were able to have functions that are more definite in what they do, this in turn greatly simplifies our code.

With the help of currying, we can essentially pre-load functions with an argument in order to receive a new function that remembers those arguments.

Let's make a function that can help us in Currying other functions.
Now pay close attention,
This function is going to take a function fn and return a function $curry that takes a single argument and performs the operation of the function fn.

Let's do this step by step

// This function takes a function `fn` as a parameter.
function curry(fn) {
  // Let us determine the arity of `fn`
  // Arity is the number of parameter taken by `fn`
  const arity = fn.length

  // ...
}
function curry(fn) {
  const arity = fn.length

  // Let's return the $curry function.
  // Let's have all the arguments ( ...args ) being passed in $curry
  // Remember we are returning a function so we can pass args in it.
  return function $curry(...args) {
    // ...
  }
}
function curry(fn) {
  const arity = fn.length
  return function $curry(...args) {
    // Let's return the function with all the passed arguments.
    // This code maybe stupid until you read the next para...
    return $curry.bind(null, ...args)

    // ...
  }
}

We can't just keep returning functions and functions we need a result. Let it be adding digits together and getting the output.

Let's add a condition for this.

function curry(fn) {
  const arity = fn.length
  return function $curry(...args) {
    if (args.length < arity) {
      return $curry.bind(null, ...args)
    }
    return fn.call(null, ...args)
  }
}

By comparing the length of the arguments args.length we can know how many arguments have been passed in the function.

Things will become more clear as I demonstrate how we are using the curry function to curry other functions which take multiple parameters.

For the sake of simplicity let's take an add function which takes 3 values (parameters) and add them together.

const add = (x, y, z) => x + y + z

const curriedAdd = curry(add)

const addFive = curriedAdd(5) // args.length = 1

const addFiveAndSix = addFive(6) // args.length = 2

const output = addFiveAndSix(8) // args.length = 3

// The funciton can be called now as `args.length` < arity is false.
console.log(output) // 19

args.length is able to give us the number of arguments because of return $curry.bind(null, ...args) . The $curry function contains all the arguments passed above the any given instance.

I hope this clears everything about how the function is working. If you have any other doubts you can tweet them to me.

( @yashguptaz )

Adding Taste to your Code.

Currying allows a wonderful phenomenon called partial application.
According to Wikipedia partial application can be defined as -

Partial Application refers to the process of fixing a number of arguments to a function, producing another function of smaller arity.

The definition is pretty straightforward, we reduce the number of parameters a function takes by currying it.

Let's curry a well-known function map and see how it changes our life.

// Before Currying
const allTheChildren = elements => map(elements, getChildren)

// Let's curry map
const map = curry((fn, f) => f.map(fn))

// AFter Currying
const allTheChildren = map(getChildren)

The effect becomes really obvious when you are using map multiple times. And that's how we reduce a ton of boilerplate code.

You can curry pretty much any function that takes more than one parameter. And use Partial Application.

Isn't it amazing? Although I am a beginner at currying I found it exciting to share. If you want to share something or ask a question or would like to solve or understand something together, you can hook me up on twitter. I am @yashguptaz on the internet.

Follow me on twitter as I tweet about my experince with Functional Programming.

Top comments (3)

Collapse
 
michaeltharrington profile image
Michael Tharrington

"I know that youโ€™re salivating, perhaps the dev world has become too delicious with JAMStack and now Iโ€™m talking about curry?"

Haha, love the opening to this article. ๐Ÿ›

Collapse
 
yashguptaz profile image
Yash

Thanks :D

Collapse
 
Sloan, the sloth mascot
Comment deleted