Point-Free Style in JavaScript

Point-Free Style in JavaScript

Daily short news for you
  • How I wish I had discovered this repository earlier. github/opensource.guide is a place that guides everyone on everything about Open Source. From how to contribute code, how to start your own open-source project, to the knowledge that anyone should know when stepping into this field 🤓

    Especially, this content is directly from Github.

    » Read more
  • Just the other day, I mentioned dokploy.com and today I came across coolify.io - another open-source project that can replace Heroku/Netlify/Vercel.

    From what I've read, Coolify operates based on Docker deployment, which allows it to run most applications.

    Coolify offers an interface and features that make application deployment simpler and easier.

    Could this be the trend for application deployment in the future? 🤔

    » Read more
  • One of the things I really like about command lines is their 'pipeline' nature. You can imagine each command as a pipe; when connected together, they create a flow of data. The output of one pipe becomes the input of another... and so on.

    In terms of application, there are many examples; you can refer to the article Practical Data Processing Using Commands on MTTQVN Statement File. By combining commands, we turn them into powerful data analysis tools.

    Recently, I combined the wrangler command with jq to make it easier to view logs from the worker. wrangler is Cloudflare's command line interface (CLI) that integrates many features. One of them helps us view logs from Worker using the command:

    $ wrangler tail --config /path/to/wrangler.toml --format json

    However, the logs from the above command contain a lot of extraneous information, spilling over the screen, while we only want to see a few important fields. So, what should we do?

    Let’s combine it with jq. jq is a very powerful JSON processing command. It makes working with JSON data in the terminal much easier. Therefore, to filter information from the logs, it’s quite simple:

    $ wrangler tail --config /path/to/wrangler.toml --format json | jq '{method: .event.request.method, url: .event.request.url, logs }'

    The above command returns structured JSON logs consisting of only 3 fields: method, url, and logs 🔥

    » Read more

The Issue

Have you ever seen code like this before?

fetch('https://api.example.com/endpoint')
  .then(toJSON)
  .then(handleResult)
  .catch(handleError);

My first encounter with this style left me quite puzzled. toJSON, handleResult, handleError – what are they here? Are they functions, and if so, where are their parameters? How can they run without ending with () to make a function call? Or at least, where are their input parameters?

Many questions swirled in my mind, but at that time, there was no one to explain it to me. What you encounter frequently becomes familiar, so I started emulating this style, implicitly thinking, "Oh, I'll just write it like this, and it will work."

It wasn't until later that I understood that this style is called Point-Free. So, if it was initially unclear, why do people still use it? Is there something mysterious or interesting about this way of writing code? Let's find out in the following article!

Point-Free Style

Point-Free style means not specifying arguments for each function application. The term "Point" refers to a function's parameter, and Point-Free means there's no "place" for those parameters. This model aims to make readers focus on what a function does, not caring about the specific names of its parameters.

Returning to a simplest example, we create four functions that, just by looking at them, you can tell what they do:

const testOdd = x => x % 2 === 1;
const testUnderFifty = x => x < 50;
const duplicate = x => x + x;
const addThree = x => x + 3;

Then, we apply a series of transformations to a list of numeric data:

const myArray = [22, 9, 60, 24, 11, 63];

const result = myArray
  .filter(testOdd)
  .map(duplicate)
  .filter(testUnderFifty)
  .map(addThree);

Looking at the data flow, from top to bottom, we filter out odd numbers, double them, filter again for numbers less than 50, and finally, add 3 to all of them.

With this style, all you see are function names, even in the data flow. This style achieves conciseness, but you have to choose meaningful, understandable function names.

Returning to the opening example, if written in the conventional way, your code might look like:

fetch("https://api.example.com/endpoint")
  .then((res) => res.json())
  .then((resJSON) => {
    const { data } = resJSON;
    const dataFiltered = data.filter((item) => item.active === true);
    return dataFiltered;
  })
  .catch((err) => {
    if (err instanceof RangeError) {
      throw new RangeError("The number is outside the range");
    } else if (err instanceof EvalError) {
      throw an EvalError("The code could not be evaluated");
    }
  });

A bit too much to read and understand, right? Let's "refactor" it a bit:

const toJSON = res => res.json();
const handleResult = data => data.filter(item => item.active === true);
const handleError = err => {
  if (err instanceof RangeError) {
    throw new RangeError("The number is outside the range");
  } else if (err instanceof EvalError) {
    throw an EvalError("The code could not be evaluated");
  }
};

fetch("https://api.example.com/endpoint")
  .then((res) => toJSON(res))
  .then((resJSON) => handleResult(resJSON))
  .catch((err) => handleError(err));

Better, but there's still redundant code. Let's make it Point-Free:

fetch('https://api.example.com/endpoint')
  .then(toJSON)
  .then(handleResult)
  .catch(handleError);

Pros and Cons

The most apparent advantage of Point-Free is that it focuses on functions rather than data, making code shorter and easier to read if you choose good function names. When combined with libraries following the Point-Free style, like ramda.js or lodash/fp, which provide numerous utility functions, it can create consistency in your project.

The second example, after being fully converted to ramda.js, might look like:

const R = require('ramda');

const isOdd = R.pipe(R.modulo(R.__, 2), R.equals(1));
const isUnderFifty = R.lt(R.__, 50);
const double = R.multiply(2);
const addThree = R.add(3);

const handle = R.pipe(
  R.filter(isOdd),
  R.map(double),
  R.filter(isUnderFifty),
  R.map(addThree)
);

const myArray = [22, 9, 60, 24, 11, 63];
handle(myArray);

However, what's an advantage for some might become a disadvantage for newcomers or those unfamiliar with the Point-Free style. It can be harder to understand or take more time to approach.

Conclusion

Point-Free is a programming style that focuses on function names and disregards the importance of arguments. With this style, we concentrate on the data flow rather than the logic behind it. For beginners, Point-Free can be challenging to read or understand. But once you get used to it, you'll find it extremely useful.

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