Javascript Proxy and Partial Function Application
Tags: javascript, functional, tutorial
Published: 2022-08-11 21:21:56

---
title: Javascript Proxy and Partial Function Application
published: true
description: A worked example of how to implement genralised partial application functions in javascript.
tags: javascript, functional, tutorial
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k223sezj1uz5xzk8tff3.jpg
# Use a ratio of 100:42 for best results.
---

This story starts, as all the best stories do, with a [Stack Overflow question](https://stackoverflow.com/questions/73306757/what-is-the-best-way-to-create-an-infinite-curry-function-in-javascript-to-allow) (before the answer had been posted, which, now I see, blows what I'm writing here out of the water 🤷‍♂️ I'm still going to do it). The question being "How do you make infinite curry?" or something like that. I like curry<sup>*</sup>, so I took a look.

One of the comments on the question is:

>  ...in an applicative language like JavaScript, it's not really "currying"

So, I thought to myself, if it's not currying, what is it? The [currying article](https://en.wikipedia.org/wiki/Currying) in Wikipedia makes this comment:

> Currying is related to, but not the same as, [partial application](https://en.wikipedia.org/wiki/Partial_application).

So I had a look at partial application. 

Partial application is where you have a unary function (a function that only takes one argument) and it returns another unary function, and so on, until you have enough arguments. For example:

``` javascript
function add3Numbers(x,y,z)
{
  return x + y + z;
}
```

Is a function that takes 3 arguments (x, y and z). To make it a partial application function, or rather function<b>s</b>, we can do this:

``` javascript
function add3Numbers(x)
{
  return function(y)
  {
    return function(z)
    {
      return x+y+z;
    }
  }
}
```

Which can be invoked like so:
``` javascript
add3Numbers(11)(8)(2022);
```

But also
```javascript
const add8yz = add3numbers(8);
add8yz(4)(5)
```

These toy examples don't really showcase the power of partial application, merely give you a taste of how it works. Its primary use is to make it easier to join functions together. Consider it akin to method chaining in object oriented languages, e.g.:

``` javascript
' abcdefghijklmnopqrstuvwxyz '.trim().toUpperCase().slice(3).replace('Q', 'q');
```

Where each method returns an object of the same type as the calling object.

What if, I pondered, I wanted to make a regular function into one capable of partial application? Can it be done?

The answer I have created is a resounding "sort of". I am using the [`.length`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/length) property of the function, which means it won't work for:

1. Variadic functions (e.g. `console.log`). This is because the number of parameters is not defined.
2. Functions that use rest parameters (e.g. `function f(a, b, ...c){}`). `.length` does not count rest parameters.
3. Functions with parameters that have default values (e.g. `function f(a, b=0){}`). In this case `.length` ignores parameters with default values.

So my solution is limited to functions that have an explicit number of parameters, and no default values for the parameters.

Any of the following forms are valid:

``` javascript
const func1 = function(a,b,c){};
function func2(a,b,c){}
const func3 = (a,b,c) => {};
```
Where do we start? Well, let me introduce you to my good friend [`Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/Proxy).

With this we can pretend to call a function while actually doing something else.

The proxy needs a handler, to do the magic. I imagined the partial functions like a linked list:

``` javascript
const handler =
{
    next: null,
    apply: function(target, thisArg, argumentsList)
    {                        
        if(this.next)
        {
            const uc = new unaryCall(argumentsList[0]);
            uc.args = thisArg.args.concat(argumentsList);
            return (new Proxy(unaryCall, this.next)).bind(uc);
        }
        else
        {
            const args = thisArg.args.concat(argumentsList);
            return initialFunction(...args);
        }
    }
};
```

The `apply` function is what replaces the regular function call. You might notice that I don't just create a proxy, but I also bind it to an object.

I was struggling to figure out how I would preserve the arguments without overwriting them. Eventually I realised I would need to some how to modify the proxy I created, and concluded that I could set the `thisArg` by binding the proxy.

So as to not hit some kind of recursion limit, each object that is bound to the proxy holds the arguments for itself and the previous objects. I think this gives faster access, but at the cost of taking up a lot more space.

At the end, i.e. if there is no next handler, then the handler returns the result of calling the original function with the accumulated arguments.

Building the list happens in a loop. I did consider recursion, as it would look more elegant, but the stack limit is smaller than the array size limit, so I erred on the side of caution:

```javascript
let handlers = [];
for(let i = 0; i < initialFunction.length; i++)
{
    const handler =
    {
        next: null,
        apply: function(target, thisArg, argumentsList)
        {                        
            if(this.next)
            {
                const uc = new unaryCall(argumentsList[0]);
                uc.args = thisArg.args.concat(argumentsList);
                return (new Proxy(unaryCall, this.next)).bind(uc);
            }
            else
            {
                const args = thisArg.args.concat(argumentsList);
                return initialFunction(...args);
            }
        }
    };

    if(handlers.length > 0)
    {
        const last = handlers[handlers.length-1];
        last.next = handler;
    }
    
    handlers.push(handler);
}

const firstUnary = new unaryCall(null);
firstPart = (new Proxy(unaryCall, handlers[0])).bind(firstUnary);
```

Creating a `unaryCall` didn't really need a parameter, but I put it in there to satisfy whatever goes on in my brain.

You can see at the top of the loop, I iterate through all the parameters of the function by using the length of the function. You can't actually access the parameters in the definition, so this is as close as it gets.

That's the bulk of it. You can see the entirety of the function in [this gist](https://gist.github.com/Mellen/f74894da78a153a33f6c7b5759465a0d)

Let me know your thoughts and any questions in the comments below!

{% embed https://gist.github.com/Mellen/f74894da78a153a33f6c7b5759465a0d %}

---
<small><sup>*</sup> Sadly I can no longer enjoy spicy hot curry due to a recently acquired medical condition, so my enjoyment is more hypothetical these days.</small>