Currying explained simply with a few examples.
The name "currying", coined by Christopher Strachey in 1967[citation > needed], is a reference to logician Haskell Curry.
This guy has a language and a programming technique named after him!
The basic idea of currying
In simple terms, a curried function is a function that returns a function. Currying is generally good when you want to prepopulate a function, like shown in the examples below.
In JavaScript, curried function looks something like this:
function add(x) {
return function (y) {
return x + y
}
}
add(1)(1) // 2But currying syntax somehow clicks together with arrow functions:
const add = x => y => x + y
add(1)(1) // 2JavaScript is cool, it can access the first function’s params in the inner function like nothing.
Calling a curried function
If you want to call a curried function you do it like this:
const one = add(1)
const two = one(1)
console.log(two) // 2You’re adding into it as you go.
Or:
add(1)(1)A curried API call example
Here’s a more realistic scenario, something that might happen in everyday work life. A curried function where the outer function can be prepopulated with a URL, and the inner function takes the required options:
// highlight-next-line
// The curried function lives in a shared directory
const getData = url => async options => {
const params = new URLSearchParams(options)
const response = await fetch(`${url}?${params.toString()}`)
return response.json()
}
// highlight-next-line
// Prepopulate it with different API endpoints
const getEmployees = getData('https://hub.dummyapis.com/employee')
const getProducts = getData('https://hub.dummyapis.com/products')
;(async () => {
// highlight-next-line
// Call the second half of the curried functions with needed options
const employees = await getEmployees({ noofRecords: 2 })
const products = await getProducts({ noofRecords: 3, currency: 'usd' })
console.log({ employees, products })
})()Play around with a working demo:
Currying a callback function
For example in React you get to deal with events and callback functions a lot.
In the following example that clickHandler fn takes an event and an id:
const Foo = ({ id }) => {
// highlight-next-line
const handleClick = (event, id) => {
if (event.target.id === id) {
// something...
}
}
return (
// highlight-next-line
<button id='foo' onClick={event => handleClick(event, id)}>
Click
</button>
)
}You can write it more concisely by currying the handleClick callback, the
click event will be passed to the innermost function:
const Foo = ({ id }) => {
// highlight-next-line
const handleClick = id => event => {
if (event.target.id === id) {
// something...
}
}
return (
<button id='foo' onClick={handleClick(id)}>
Click
</button>
)
}That’s purely cosmetic though, I can understand if someone finds that to be a bit extra.
Other examples
A random example of currying: styled-components syntax assumes currying when extending components while using the style object syntax:
const RedParagraph = styled(Paragraph)({
color: 'red',
})Conclusions
You can probably sail your JavaScript career through without ever writing a curried function, but in some cases it feels very elegant.
Hope this was helpful, thanks for perusing my little blog article!