Forever Functional: Simpler code through Partial Application
Tags: javascript, programming
Published: 2023-05-30 23:28:47

by [Federico Kereki](https://blog.openreplay.com/authors/federico-kereki)

<blockquote><em>"Partial Application" may sound like a complex thing, but it is actually quite a powerful tool that will simplify the way you work, and this article will show you how to easily implement it for your JavaScript code.</em></blockquote>


When we discussed [higher-order functions](https://blog.openreplay.com/forever-functional-higher-order-functions-functions-to-rule-functions/) such as [decorators](https://blog.openreplay.com/forever-functional-decorators-higher-order-functions/), we saw several ways of working with a function to produce a new version that would have some change in its functionality, such as adding logging or timing among many examples. 

Let's now consider another kind of transformation that will not change what the function does but will allow you to simplify your work: [partial application](https://en.wikipedia.org/wiki/Partial_application). If you have a function that expects several parameters, partial application lets you fix the values of some of them, producing a new function that will expect the missing parameters. When you provide all the pending parameters, the original function is called, and the actual calculation is performed.

## Why use partial application?

Before getting to the details of how to do partial application, let's give some examples. Imagine you had an `addTax(moneyAmount, taxRate)` function that would compute the required taxes for a given money amount along the lines of the following:

```javascript
const addTax = (moneyAmount, taxRate): number => {
  return moneyAmount + moneyAmount * rate / 100;
}
```

For example, if you wrote `addTax(400, 5)`, the result would be 420; 400 plus 5% of 400, which is 20. If you always have to add a fixed, constant rate, you can use partial application to produce a specialized version of the `addTax(...)` function. For instance, in my country (Uruguay) the usual tax rate is 22%, so I could write something like the following:

```javascript
const addUruguayTax = addTax(undefined, 22);  // this won't (yet) work!
```

This code doesn´t really work because `addTax(...)` doesn't know what to do with the `undefined` amount, but we'll get to that; bear with me. As the result of partial application, `addUruguayTax(...)` would now be a function expecting a single parameter. We could use this function as follows:

```javascript
const totalSalesPlusUruguayTax = addUruguayTax(totalSales);
```

Given a `totalSales`, then `totalSalesPlusUruguayTax` would include the national VAT; nice!

A possible objection: why go to all this bother when you could just write the following?

```javascript
const addUruguayTax = (moneyAmount) => addTax(moneyAmount, 22);
```

The question is valid, and for simple functions such as `addTax(...)` with just a couple of parameters, using partial application can be overkill. The real benefits come when working with functions that receive many parameters, because now you can be able to fix any of them as you may need.

For instance, if you had a `nonSensical(a,b,c,d,e,f)` function with six parameters, there are 63 different ways in which you can provide some parameters and leave others unfixed; you wouldn't be able to handle this easily with plain arrow functions! So, let's now see how we can write a general `partialize(...)` solution.

## Implementing partial application

In some languages, doing partial application in a totally general way would be hard or impossible, but JavaScript (and therefore TypeScript as well) lets us do it by taking advantage of [closures](https://en.wikipedia.org/wiki/Closure_(computer_programming)), as we'll see now. 

We first need a way to specify which parameters are to be fixed and which are still pending. Some libraries use special placeholders (like [Ramda](https://ramdajs.com/docs/), which uses `R.__`, or [Underscore](https://underscorejs.org/docs/modules/partial.html), which uses `_`) but I think `undefined` fits the bill and can be used to represent missing values.

The following code (from my [Mastering JavaScript Functional Programming](https://www.amazon.com/Mastering-JavaScript-Functional-Programming-maintainable/dp/1804610135/ref=sr_1_5) book) does the job:

```javascript
function partial(fn) {
  const partialize =
    (...args1) =>
    (...args2) => {
      for (let i = 0; i < args1.length && args2.length; i++) {               1️⃣
        if (args1[i] === undefined) {
          args1[i] = args2.shift();
        }
      }
        
      const allParams = [...args1, ...args2];                                2️⃣
      
      return !allParams.includes(undefined) && allParams.length >= fn.length 
        ? fn(...allParams)                                                   3️⃣
        : partialize(...allParams);                                          4️⃣
    };
  return partialize();
}
```

This is not simple to understand! The inner `partialize()` function is key: given a list of parameters (`args1`) it returns a new function that will expect a second list of parameters ( `args2`) in the following way:

* 1️⃣ it will attempt to replace possible `undefined` values in `args1` with values taken from `args2`.
* 2️⃣ if any parameters are still left in `args2`, it will add them to the (updated) list at `args1`, producing a new `allParams` list
* 3️⃣ if `allParams` doesn't include any (pending) `undefined` values and has all the parameters that the `fn` function expected, the original function is called
* 4️⃣ otherwise, if some parameters are still pending, the function recursively partializes itself to return a new function with more fixed (but still not all) parameters.

Let's see a simple example and also go back to our taxes-calculating function.


<div style="background-color:#efefef; border-radius:8px; padding:10px; display:block;">
<hr/>
<h3><em>Session Replay for Developers</em></h3> 
<p><em>Uncover frustrations, understand bugs and fix slowdowns like never before with <strong><a href="https://github.com/openreplay/openreplay" target="_blank">OpenReplay</a></strong> — an open-source session replay suite for developers. It can be <strong>self-hosted</strong> in minutes, giving you complete control over your customer data.</em></p>
<img alt="OpenReplay" style="margin-top:5px; margin-bottom:5px;" width="768" height="400" src="https://raw.githubusercontent.com/openreplay/openreplay/main/static/openreplay-git-hero.svg" class="astro-UXNKDZ4E" loading="lazy" decoding="async">
<p><em>Happy debugging! <a href="https://openreplay.com" target="_blank">Try using OpenReplay today.</a></em><p>
<hr/>
</div>


## Some examples of use

Let's start with a simple `makeBigString(...)` function, which expects six values and returns a string with all of them.

```javascript
const makeBigString = (a, b, c, d, e, f) => `${a}${b}${c}${d}${e}${f}`;

const partialMakeBigString = partial(makeBigString);

/*
 * Or write:
 * 
 * const makeBigString = partial((a,b,c,d,e,f) => `${a}${b}${c}${d}${e}${f}`);
 * 
 */
```

Then, you can write:

```javascript
partialMakeBigString(undefined,2,undefined,undefined,5)(undefined,3)(1,4)(6);

// result is "123456"
```

Let's follow what is happening here, step by step:
* first, `partialMakeBigString(undefined,2,undefined,undefined,5)` returns a new version of the original function that fixes its 2nd and 5th parameters, leaving all the rest undefined.
* calling that function with `(undefined,3)` fixes its 2nd parameter (which actually is the 3rd parameter of the original function) and produces a new function that still expects three more parameters
* calling the latest function with `(1,4)` fixes the first two of the three parameters and produces a new function that needs just one parameter
* providing `(6)` to the last function actually finishes fixing all the parameters of the original function, which is then called to produce `"123456"`.

How would we do our original taxes example? There are two ways. We could use partial application when defining `addUruguayTax(...)` as in:

```javascript
const addUruguayTax = partial(addTax)(undefined, 22);
```

Or (better yet, in my opinion) we could have defined `addTax(...)` from the beginning to allow partial application:

```javascript
const addTax = partial((moneyAmount, taxRate): number => {
  return moneyAmount + moneyAmount * rate / 100;
})
```

Both solutions work, but I think the first one is harder to understand--having two sets of parentheses in a row is not common. 

## Conclusion

Partial application is an interesting technique that simplifies working with functions, whenever you foresee the possibility or need for providing just a few parameters at a time, producing a function that, at a later time, will receive the pending rest. Implementation takes advantage of closures and recursion, highlighting all the facilities JavaScript includes to allow very functional ways of working!