Skip to content

Instantly share code, notes, and snippets.

@rpivo
Last active December 28, 2020 01:39
Show Gist options
  • Save rpivo/d2880f4e9f069b6e4c0ef396b76098fb to your computer and use it in GitHub Desktop.
Save rpivo/d2880f4e9f069b6e4c0ef396b76098fb to your computer and use it in GitHub Desktop.
Point-Free Style in JavaScript

Point-Free Style in JavaScript

Point-free style is a really cool mechanic that can help establish good practices in regards to functional programming.

const arr = [1,2,3]

arr.forEach(console.log)

Output:

1 0 [ 1, 2, 3 ]
2 1 [ 1, 2, 3 ]
3 2 [ 1, 2, 3 ]

What's going on here?

Normally, we would see forEach used with a callback.

arr.forEach((curr, idx, arr) => console.log(curr, idx, arr))

Output:

1 0 [ 1, 2, 3 ]
2 1 [ 1, 2, 3 ]
3 2 [ 1, 2, 3 ]

With point-free style, we implicitly pipe the incoming arguments into the callback function.

(curr, idx, arr) => console.log(curr, idx, arr)

// we can simplify and imply that the arguments will go into the callback function, and it will just work

console.log

This will work with any callback function wherein the parent function needs to pass in values to the callback. The pattern is especially useful with iterables.

const strArr = ['FOO', 'BAR', 'BAZ']

function getLowerCase(val) { return val.toLowerCase() }

// point-free version of strArr.map(item => getLowerCase(item))
const lower = strArr.map(getLowerCase)

console.log(lower)
// [ 'foo', 'bar', 'baz' ]

Here's another example using Array.prototype.every.

function isOddValue(value) { return value % 2 === 1 }

const arr = [1,3,5]

console.log(
  // point-free version of arr.every(item => isOddValue(item))
  arr.every(isOddValue)
)
// true

This snippet of code has two examples of point-free style.

function resolver(cb) { cb(1) }

const p = new Promise(resolver)

p.then(console.log)

Output:

1

In this example, we're passing the promise's first argument (the resolving function) into resolver. resolver then calls this function. This causes the promise's then branch to be entered since the promise resolved.

We use point-free style again to implicitly pipe the resolved value into the console.log(), resulting in the value 1 being printed.

Any time you see a callback function, there is probably a simplified point-free solution that can be implemented.

map(value => cb(value))

/* equivalent to */

map(cb)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment