Which one of the following equivalent implementation do you prefer?

```[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.filter(int => isEven(int))
.filter(int => isBiggerThan(3, int))
.map(int => int + 1)
.map(int => toChar(int))
.filter(char => !isVowel(char))
.join(‘’)```
`// ‘fhjl’`

vs

```[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.filter(isEven)
.filter(isBiggerThan(3))
.map(plus(1))
.map(toChar)
.filter(not(isVowel))
.join(‘’)```
`// ‘fhjl’`

I’d argue the second one is waaaay more readable. The secret is removing the arguments from the `filter`s and `map`s.

Let’s see how it works. I promise, once you see how that works, you won’t be able to unsee it anymore.

#### A Simple Function

Let’s take a sum function

`const sum = (a, b) => a + b`
```sum(1, 2)
// 3```

and rewrite it in a different way

`const csum = a => b => a + b`
```sum(1)(2)
// 3```

They work the same, the only difference is how you call them: `sum` accepts two parameters at once, `csum` accepts parameters one by one. In particular, let’s say you call `csum` only once with the term `1`

```csum(1)
// b => 1 + b```

then you get back a function that accepts the second term and returns it incremented by one

`const plusOne = csum(1)`
```plusOne(2)
// 3```

#### Operating on Arrays

In JavaScript arrays can be manipulated with various methods. For instance, `map` is used to apply the same function to each element of an array.

To increment each integer in an array

```[1, 2, 3].map(x => x + 1)
// [2, 3, 4]```

In other words, `x => x + 1` takes an integer and returns its successor. Using `plusOne` from above the function can be rewritten to

```[1, 2, 3].map(x => plusOne(x))
// [2, 3, 4]```

But wait a sec, `x => plusOne(x)` and just `plusOne` are equivalent, in fact

```const otherPlusOne = x => plusOne(x)
otherPlusOne(1)
// 2```
```plusOne(1)
// 2```

For the same reason

```[1, 2, 3].map(x => plusOne(x))
// [2, 3, 4]```

is equivalent to

```[1, 2, 3].map(plusOne)
// [2, 3, 4]```

and since `plusOne` was defined above as `const plusOne = csum(1)`

```[1, 2, 3].map(csum(1))
// [2, 3, 4]```

Now your turn, apply the same process used for `sum` to `isBiggerThan` so that you don’t need to specify arguments in the `filter` (ie `int =>`)

`const isBiggerThan = (threshold, int) => int > threshold`
`[1, 2, 3, 4].filter(int => isBiggerThan(3, int))`

Now the code from the intro shouldn’t have any more secrets to you.

```[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
.filter(isEven)
.filter(isBiggerThan(3))
.map(plus(1))
.map(toChar)
.filter(not(isVowel))
.join(‘’)```
`// ‘fhjl’`

#### Two Simple Rules

Rule 1

The following two are equivalent

`[…].map(x => fnc(x))`
`[…].map(fnc)`

Rule 2

It’s always possible to rewrite a callback to remove arguments

```const fnc = (x, y, z) => …
[…].map(x => fnc(x, y, z))```
```const fnc = (y, z) => x => …
[…].map(fnc(y, z))```

You’ve prolly applied this transformation if you’ve worked on the `isBiggerThan` exercise. In fact, let’s say we want to keep integers bigger than `3`

```const isBiggerThan = (threshold, int) => int > threshold
[…].filter(int => isBiggerThan(3, int))```

Now we can rewrite `isBiggerThan` to remove the `int =>` part in the `filter`

```const isBiggerThan = threshold => int => int > threshold
[…].map(isBiggerThan(3))```

#### Go After It

Let’s say you have

```const keepGreatestChar =
(char1, char2) => char1 > char2 ? char1 : char2```
```keepGreatestChar(‘b’, ‘f’)
// ‘f’
// because ‘f’ comes after ‘b’```

Rewrite `keepGreatestCharBetweenBAnd` to remove the `char` argument

```const keepGreatestChar =
(char1, char2) => char1 > char2 ? char1 : char2```
```const keepGreatestCharBetweenBAnd = char =>
keepGreatestChar(‘b’, char)```
```keepGreatestCharBetweenBAnd(‘a’)
// ‘b’
// because ‘b’ comes after ‘a’```

Rewrite `greatestCharInArray` using `keepGreatestChar` to remove the arguments (ie `(acc, char)`) from inside `reduce`

```const keepGreatestChar =
(char1, char2) => char1 > char2 ? char1 : char2```
```const greatestCharInArray =
array => array.reduce((acc, char) => acc > char ? acc : char, ‘a’)```
```greatestCharInArray([‘a’, ‘b’, ‘c’, ‘d’])
// ‘d’```

Implement `creduce` so that `greatestCharInArray` can employ it and not need any arguments

```const creduce = …
const greatestCharInArray =
array => array.reduce((acc, char) => acc > char ? acc : char, ‘a’)```

`creduce` should be generic enough to be applied to any problems that require a reduce operation. In other words, it should receive callback, an init value and the array to operate upon.

Hint: you want to be able to write

`const greatestCharInArray = creduce(keepGreatestChar, ‘a’)`
```greatestCharInArray([‘a’, ‘b’, ‘c’, ‘d’])
// ‘d’```

#### What the Hell is that `c` in `csum` and `creduce`?

`c` stands for curried and what you’ve seen above is how curried functions can make your code more readable. To be precise I haven’t used proper curried functions in this article but that’s good enough.

If you want to dig deeper the art and science of curried functions I recommend reading Chapter 4 of Mostly Adequate Guide to Functional Programming. And since you are there, trust me, read the book entirely.

Also, if you want to read more about functional programming in JavaScript, take a look at FP in vanilla JavaScript: a rookie’s intro.