# Curry Functions in JavaScript

## What is it?
Curry functions are not asian spiced functions. I do love curry chicken and the lot, but, alas, that is not what we are talking about here.

Currying a function sounds complex, but in practice it is quite straightforward. Start by writing a basic JavaScript function (using ES6 syntax);
```
const addThree = (number) => {
    return a + 3;
};

addThree(4);   // => 7 
```
What if we wanted a function that added four, not three? Maybe we create another function `addFour` and do something similar.
```
const addFour = (number) => {
    return a + 4;
};

addFour(5);   // => 9
```
However, we are software developers; simplicity, readability, and "working smarter not harder" should always be a goal. We aren't software *engineers* for nothing. Our very job is to automate and solve problems using software.

Here is where curried functions fit in. In one function, you can build two functions that can `addFour` AND `addThree`. Here's how.
```
const add = (amount) => (number) => {
    return number + amount;
};

const addThree = add(3);
const addFour = add(4);

addThree(3); // => 6
addFour(8); // => 12
```
For those of you familiar with arrow function notation, this may look funky but you probably get it. It's purely a function returning... another function. If it helps, here is another way to write this curried `add` function:
```
const add = (amount) => {
    return (number) => {
        return number + amount;
    }
};
```
Do you see the abstraction? The possibilities? Now if you wanted more functions, maybe `addFive` or `addSix`, you wouldn't need to create new functions, you could simple do:
```
const addFive = add(5);
const addSix = add(6);
```

You might be wondering why you wouldn't just do `const add = (amount, number) => ...`. Valid question.

Currying allows for **partial application**. A partial application is a function which has been applied to some, but not yet all of its arguments.

## Use case
I recently build a complaint forum application to try out a new tech stack I was interested in: Svelte + Tailwind + Airtable (as DB) + AWS S3 (purely static).

I used Airtable as my db *and* backend (using their API). I created a wrapper function in order to interact with my different tables: complaints, users, comments, and threads.
```
const baseUrl = "https://api.airtable.com/v0/<airtable-project-key>"

const createFetcher = table => async ({
  method = 'GET',
  params = '',
  id = '',
  data = {}
} = {}) => {
  const extras = {
    headers: {
      'Authorization': 'Bearer <airtable-api-key>',
      'Content-Type': 'application/json',
    },
    method,
  };

  if (method !== 'GET') {
    extras.body = JSON.stringify(data)
  }

  if (!!params) {
    params = Object.keys(params).map(function(key) {
      return key + '=' + params[key];
    }).join('&');
  }

  const res = await fetch(baseUrl + `/${table}${id ? '/' + id : ''}?` + params, extras)

  return res.json()
}

export const Complaints = createFetcher('Complaints')
export const Comments = createFetcher('Comments')
export const Threads = createFetcher('Threads')
export const Users = createFetcher('Users')
```

### Breakdown
the `createFetcher` is a curried function that allows you to create a wrapper around each table without having to do all the fetch boilerplate work. Then at the bottom I create a fetcher function for each table. 

### Usage

To delete a thread.. or comment.
```
Threads({
    method: 'DELETE',
    id: threadId
});

Comments({
    method: 'DELETE',
    id: commentId
});
```
And there you have it; need to delete a Complaint? You know what to do.

Till next time,
Cheers.




