I'm not sure if i just haven't drunk enough koolaid or if curriers are beyond the pale.
I'm not sure if i just haven't drunk enough koolaid or if curriers are beyond the pale.
The closest real world example I can think of right now is calling a webservice. Which is usually something like
const baseUrl = 'https://some.tld'
function callExternal(resourcePath, data) {
fetch(baseUrl + resourcePath, data)...
}
// and then somewhere
callExternal('/some/path', {some: data})
With currying you could do it like this: const baseFun = function(baseUrl, resourcePath, data) {
fetch(baseUrl + resourcePath, data)...
}
const callExternal = baseFun('https://some.tld')
// ^ you "pin" the first argument to always be 'https://some.tld'
// and then somewhere
callExternal('/some/path', {some: data})
I personally have had the need to write a curried function myself maybe twice over the course of the past 17 years.Of course, one can wonder how many times can one usefully curry with external functions, but I think that's partially a result of not having currying syntax in the first place. For example, the fact that Ruby has blocks massively influences the typical design of its libraries, when compared to Python.
Now you can think of an array as a restricted function whose domain is 0..n x ... and range is some type. The same concept of "currying" applies to functions. That is, given a function of N arguments, if you provide K (less than N) arguments you get another function of N-K arguments.
It is strange that many programming languages allow currying of arrays but not of functions!
edit: a word
Stupid examples are in many cases worse than no examples at all.
I have an array of objects in my state. For this example we'll say they are Todos, and each one has three properties, id, name, and checked. I have a function `checkTodo` with the signature `checkTodo(id: string, event: InputEvent)` that I want to call if one of those Todos is checked.
So say I'm using React. I can use arrow functions like this:
todos.map((todo) =>
<input type="checkbox" onChange={ (event) => checkTodo(todo.id, event) } checked={ todo.checked } />
<label>{ todo.name }
)
That's okay, but having arrow functions like that in JSX (which you'll have several of in a complex application) can get a bit unwieldy. Currying gives us another option that can be cleaner and avoids having to declare functions inside our render. If we change our method signature to this: `checkTodo = (id: string) => (event: InputEvent)` then we can write our JSX like this: todos.map((todo) =>
<input type="checkbox" onChange={ checkTodo(todo.id) } checked={ todo.checked } /><label>{ todo.name }
)
It's a bit cleaner, and can make certain patterns a lot easier in the long run. For example, say we make a shared <Todo /> component like the one above which can be rendered both in a list, as above, or on it's own. In that case, it would be bad for the method signature that the Todo component expects to be the id and event, as the id wouldn't be necessary when we're not working with an array.Instead, currying means our Todo component can simply expect a function that takes in an InputEvent, and currying can move the other logic where it's needed.
Does that make sense? If you don't know React I could rewrite this using native DOM calls.