:books: Today I Learned

Cool functional programming features may be coming to JavaScript

programming JavaScript javascript tc39 functional

I’ve been learning functional programming languages lately, so I was happy to see some of my favorite functional programming features in the TC39 stage 1 proposals.

The pipeline operator

I know the pipe operator from Elixir and from Elm. The ECMAScript pipeline operator proposal introduces a similar operator |> which allows you to streamline chained function calls in a readable, functional manner.

Let’s assume you have the following functions available:

function doubleSay(str) {
  return str + ", " + str;
}
function capitalize(str) {
  return str[0].toUpperCase() + str.substring(1);
}
function exclaim(str) {
  return str + '!';
}

Chaining them is not very readable because the functions do not execute in the order they appear in the code. Your brain has to get used to reading them from the inside to the outside of the chain:

// The order of execution is: doubleSay,
// then capitalize, then exclaim.
let result = exclaim(capitalize(doubleSay("hello")));
console.log(result);  //=> "Hello, hello!"

With the new pipeline operator, the following execution would be equivalent and much more intuitive to read and understand:

let result = "hello"
  |> doubleSay
  |> capitalize
  |> exclaim;

console.log(result);  //=> "Hello, hello!"

Pattern matching

I’ve used pattern matching in Elixir, in Elm and in Rust. The ECMAScript pattern matching proposal would add a similar expression based on the existing destructuring assignment.

It allows compact destructuring of complex data types in a switch-like manner:

const res = await fetch(jsonService);

case (res) {
  when {status: 200, headers: {'Content-Length': s}} ->
    console.log(`size is ${s}`),
  when {status: 404} ->
    console.log('JSON not found'),
  when {status} if (status >= 400) -> {
    throw new RequestError(res)
  },
}

Partial application

I’ve used partial application in Elm and with the Lodash-like Ramda library for JavaScript.

Let’s say you have a generic addition function like this:

function add(x, y) {
  return x + y;
}

You can use existing JavaScript features to create a partially-applied version of this function. Let’s say you often need to increment by 1 and want to derive this functionality from the existing function. You could use Function.prototype.bind:

const incrementByOne = add.bind(null, 1);
incrementByOne(2); // 3

Or you could use an arrow function:

const incrementByOne = x => add(x, 10);
incrementByOne(3);  // 4

The partial application proposal introduces a more compact way of doing this:

const incrementByOne = add(1, ?);
incrementByOne(4); // 5

This would interact very nicely with the previously-mentioned pipeline operator proposal:

let newScore = clamp(0, 100, add(7, player.score));

// This would be an equivalent expression using
// the pipeline operator and partial application:
let newScore = player.score
  |> add(7, ?)
  |> clamp(0, 100, ?);

Do expressions

I’ve long enjoyed programming in languages where every expression returns a value. This is generally the case in functional programming languages like Elixir and Elm, but also in some other languages like Ruby.

In JavaScript, this is an expression:

1 + 2

You can store its result into a variable:

const value = 1 + 2;
console.log(value);  // 3

However, the if statement in JavaScript is not an expression, so you cannot do this:

const value = if (someCondition) {
  1
} else if (someOtherCondition) {
  2
} else {
  3
}

You are forced to do something like this:

let value;
if (someCondition) {
  value = 1;
} else if (someOtherCondition) {
  value = 2;
} else {
  value = 3;
}

The do expressions proposal adds a more expression-oriented of doing this:

const value = do {
  if (someCondition) {
    1
  } else if (someOtherCondition) {
    2
  } else {
    3
  }
};

Meta

TC39 is a group of JavaScript developers, implementers, academics, and more, collaborating with the community to maintain and evolve the definition of JavaScript.

The TC39 proposals are the changes proposed to ECMAScript, the JavaScript standard. Stage 1 proposals are early in the process and have not yet been standardized.