Clean Partial Application in Javascript

22/12/2018

Partial application, prevelent in functional programming languages, allows programmers to call a function with only some of its arguments, returning a partially applied function, a function that takes in the remaining arguments.

In Javascript however, standard functions cannot be partially applied. Calling functions with arguments missing results in the argument being undefined, and the function is executed with only some of it's arguments supplied.

// A regular function
const regular = function(a,b,c) {
    console.log(a,b,c);
}

// You can call it with 0,1,2,3 arguments
regular(1);     // 1, undefined, undefined
regular(1,2);   // 1, 2, undefined
regular(1,2,3); // 1, 2, 3
regular();      // undefined, undefined, undefined

// However, you cannot partially apply it :(
regular(1)(2); // 'Uncaught TypeError: regular(...) is not a function'

There is of course a way around this, and that's to instead return a function expecting the remaining arguments, like so:

// A function that returns another function using a parameter
const partial = function(inp) {
    return function () {
        console.log(inp);
    }
}

// logHello contains the function partial returns
var logHello = partial("Hello!");

logHello(); // "Hello!"
partial("Hello!")(); // "Hello!"

However, this gets extremely messy as we use this with functions that take many arguments...

// This gets very annoying very quickly...
// Not to mention hard to read!
const nested = function (a) {
    return function(b) {
        return function(c) {
            return function(d) {
                console.log(a + b + c + d);
            }
        }
    }
}

nested("a")("b")("c")("d"); // "abcd"

Perhaps arrow functions can lend us a hand with their stripped down notation?

// Can the arrow notation help?
// Not much better.

const arrows = (a) => {
    return (b) => {
        return (c) => {
            return (d) => {
                console.log(a + b + c + d);
            }
        }
    }
}

// But partial application still works!
arrows("a")("b")("c")("d"); // "abcd"
const partial = arrow("a")("b");
partial("c")("d"); // "abcd"

Until we remember; Arrow functions have syntax to return a single expression!

// We can use the single statement capability!
// We can even omit the braces here to create a one-line function (try it!).
const arrow = a => b => c => d => { 
    console.log(a + b + c + d);
}

arrow("a")("b")("c")("d"); // "abcd"

const partiallyApplied = arrow("This ")("is ");
partiallyApplied("a ")("message!"); // "This is a message!"

Hooray! Nice and clean partial application in the web :)