What is a Curry function? A delicious "curry" dish and how to enjoy it?

What is a Curry function? A delicious "curry" dish and how to enjoy it?

Daily short news for you
  • I just discovered the idb-keyval library that helps implement a key-value database simply. As shared in the series of posts about the process of making OpenNotas, I was struggling to find a type of database for storage, and it seemed quite difficult; in the end, I settled on localForage.

    idb-keyval is quite similar to localForage, but it seems to be doing a little better. For example, it has an update function to update data, simply imagine it like this:

    update('counter', (val) => (val || 0) + 1);

    Unlike the set function, which completely replaces the data.

    » Read more
  • At the beginning of the new year, may I share the amount earned after 1 month of advertising at indieboosting.com 🥳🥳🥳

    » Read more
  • Since the Lunar New Year holiday has started, I won't be posting anymore. See you all after the holiday! 😁

    » Read more

The Problem

For every programmer, writing reusable code is essential. Each person has their own ways of achieving this, such as creating libraries of useful code snippets. But in this article, let's focus more on a micro-level approach, at the function level.

What is a Curry function?

The concept of a curry function is quite simple - it is a regular JavaScript function that takes multiple arguments as a series of single-argument functions. For example:

function sum(a) {
  return function add(b) {
    return a + b;
  }
}

const add1 = sum(1);
const result = add1(2);
console.log(result); // 3;

// Alternatively, we can write it more concisely as:  
const result =  sum(1)(2);
console.log(result); // 3

Oh, the syntax seems unfamiliar, doesn't it? So what benefits does it bring?

Why Curry function?

There are two things that curry functions can bring:

  • Smaller functions can express the problem more clearly and can be easily reused without clutter.
  • Functions can be used repeatedly.

Let me provide examples to clarify these two points.

Smaller functions express better

In the first example, I have an array of objects with id and name, and I want to extract only the id:

const objects = [{ id: 1, name: "A" }, { id: 2, name: "B" }, { id: 3, name: "C" }];
const ids = objects.map(function (o) { return o.id; });

It looks simple, right? But there is a problem with function (o) { return o.id; } - it works, but it can be better. Let's improve it:

function get(attr) {
  return function getAttr(obj) {
    return obj[attr];
  }
}
const ids = objects.map(get("id"));

get is a curry function. It takes an attr to serve the purpose of extracting a specific attribute and an obj as the object to be extracted.

You may find the syntax in ids a bit confusing, so let's recall the map function in JavaScript:

Array.map(function (i) { return i; });

.map takes a function as a parameter, which has access to each element in the array for processing.

In other words, this is actually what ids does:

const ids = objects.map(function (o) { return get("id")(o); });

Now do you understand? So here's a question for you: if I want to reuse the function that extracts id from objects, how would I do it? Is it like this:

function getIds(objs) {
  return objects.map(get("id"));
}

getIds(objects);

It seems to work, but it can still be improved. Why don't we apply curry function to create a function called "map" that loops through the elements in an array?

function map(func) {
  return function exec(value) {
    return value.map(func);
  }
}

const getIds = map(get("id"));
getIds(objects);

Here, I can see that if basic functions are curried, I can easily create a new function that performs a different functionality from them. And another thing is that the code is written in a very readable manner, making it clear what it does at first glance.

Translucent functionality

One advantage of curry functions is that they allow your code to focus more on the specific functionality rather than being a regular function. In the examples above, using curry functions makes the code look more understandable:

fetchData()
  .then(JSON.parse)
  .then(function(data){ return data.posts })
  .then(function(posts){
    return posts.map(function(post){ return post.title })
  });

You may have a different way to write it, but in this case, I want to emphasize that using curry functions will make the code look more understandable:

fetchData()
  .then(JSON.parse)
  .then(get("posts")
  .then(map(get("id")));

Thanks to the benefits of curry functions, there are quite a few supporting libraries such as the curry and curry functions in Ramda, a famous library for functional programming.

Summary

Curry functions are a way to "play" with functions, making it easier to understand and utilize the benefits they bring. If you find it fascinating, try applying it to your next project starting from now.

Premium
Hello

5 profound lessons

Every product comes with stories. The success of others is an inspiration for many to follow. 5 lessons learned have changed me forever. How about you? Click now!

Every product comes with stories. The success of others is an inspiration for many to follow. 5 lessons learned have changed me forever. How about you? Click now!

View all

Subscribe to receive new article notifications

or
* The summary newsletter is sent every 1-2 weeks, cancel anytime.

Comments (0)

Leave a comment...
Scroll or click to go to the next page