Partial Application in Action
Have you ever found yourself calling the same function with the same argument, over and over again? Well, I have some good news for you. There’s a simple technique that can help you reduce this kind of repetition and it’s called partial application. Say you have a function that adds two numbers:
const add = (a, b) => a + b
add(2, 4)
// 6
Function.prototype.bind
allows you to partially apply a function by passing it the arguments you want to fix.
For example, if you partially apply add
, fixing the first argument with a value of 10
, the result is a new function addTen
that adds 10
to the remaining argument.
const add = (a, b) => a + b
const addTen = add.bind(null, 10)
addTen(3)
// 13
addTen(6)
// 16
This is a common example of partial application but it’s not that useful in the real world. Here is a more practical example:
Reducing argument repetition
Say you want to fetch three different resources from an API, your code might look something like this:
const apiBaseUrl = 'https://api.myapp.com/api/v1'
const getData = (baseUrl, resource) => fetch(`${baseUrl}/${resource}`)
Promise.all([
getData(apiBaseUrl, 'products'),
getData(apiBaseUrl, 'categories'),
getData(apiBaseUrl, 'tags'),
]).then((responses) => {
// Do stuff
})
Notice that getData
and the first argument apiBaseUrl
are repeated. You can use partial application to remove this repetition.
If you partially apply getData
, fixing the first argument with the value of apiBaseUrl
, the result is a new function that takes the remaining argument resource
:
const apiBaseUrl = 'https://api.myapp.com/api/v1'
const getData = (baseUrl, resource) => fetch(`${baseUrl}/${resource}`)
const getDataFromAPI = getData.bind(null, apiBaseUrl)
Promise.all([
('products'),
getDataFromAPI('categories'),
getDataFromAPI('tags'),
]).then((responses) => {
// Do stuff
})
That’s a bit better. apiBaseUrl
is no longer repeated but you can take it a step further by removing the repeated calls to getDataFromAPI
.
Reducing function call repetition
By using partial application, you created a new function getDataFromAPI
that takes a single argument. This allows you to pass it to the map
function of an array, like so:
const apiBaseUrl = 'https://api.myapp.com/api/v1'
const getData = (baseUrl, path) => fetch(`${baseUrl}/${path}`)
const getDataFromAPI = getData.bind(null, apiBaseUrl)
Promise.all(['products', 'categories', 'tags'].map(getDataFromAPI)).then(
(responses) => {
// Do stuff
}
)
Now there is no repetition. The code is concise but is it more readable? Let me know what you think.
Discuss on Twitter • Edit on GitHub
Keep Reading
- Why Use a JavaScript Framework
13 Jul 2019 - Rendering Children in React
06 Feb 2019 - Hacking Image Interpolation for Fun and Profit
13 Jan 2019 - The Perils of Jest Snapshot Testing
07 Jan 2019 - A Better Way to Test Your React-Redux App
01 Jan 2019 - Firebase + Create React App
01 Aug 2018 - Partial Application in Action
29 Sep 2017 - Using SVG to Shrink Your PNGs
07 Sep 2014 - Adaptive Content
06 Feb 2013