Photo by Daniel von Appen on Unsplash

Currying function with named parameters in JavaScript

Dimitri Nikogosov
Webtips
Published in
5 min readNov 3, 2017

--

I work in a biotech company, exploring and developing how to integrate heterogeneous biological data about a person, sometimes finding a solution of different applied and theoretical problems in programming and genetics.

In the first post, let’s talk about currying of functions with named parameters in JavaScript.

There are two general ways to abstract something in almost every programming language: variables and functions. While a variable is just an abstraction over some calculation, a function goes further and parameterises such abstraction.

You can think about function as an abstraction with parameters:

Function with named parameters

If a function has more than one parameter and the time comes to apply the function, there is a need to distinguish between parameters. There are two ways of parameter discrimination: by order and by name.

Parameters that differ from each other in order are called positional parameters. Otherwise, they are named parameters.

Here are some abbreviations:

  • PPF is a function with positional parameters where you have no notion about the parameters’ names during application. A caller uses the parameter’s position to distinguish it.
  • NPF is a function with named parameters. A caller uses a parameter’s name during application explicitly.

The following two functions are examples of PPF:

JavaScript doesn’t have native support for named parameters like other languages but there is a tricky simulation: to name parameters via an object literal, passed as a single actual parameter.

We can convert above functions into NPF by ES6's parameter destructuring feature:

Now you can pass an object with any order of properties to the function. Only expected arguments will be extracted by destructuring mechanism:

Currying

The name currying is a reference to logician Haskell Curry. Nevertheless, the concept was originally proposed by another logician, Moses Schönfinkel.

Currying is the technique of rewriting a function with multiple arguments into a sequence of functions with a single argument.

In the case of our ppfSearch() function it means the following:

Pay attention to the two fat arrows in the curried version instead of the single arrow in the basic version.

If the curried version applied to only one, haystack argument, it will return a new function that waits for remaining needle argument. The process of applying a function to the subset of its arguments is called partial application:

You can curry a function with any number of arguments greater than one (it is a meaningless action in case of unary function).

But if you want to apply a manually curried function to the all set of arguments in JavaScript you need to use extra parentheses, otherwise you will still get a partially applied function:

It‘s cool to be able to apply a curried function to any appropriate set of arguments without worrying about parentheses. There is a method called autocurrying. Suppose you have the curry() function that converts basic PPF to the curried one with autocurry feature:

It works. The curry() function already exists in several functional libraries like Ramda and Sanctuary.

So, how to curry a function procedurally? How does the curry() function work? The idea behind currying is pretty easy:

  1. Get the function’s parameter list to know what parameters are expected.
  2. Then you’re watching what parameters are obtained and what remain: if given arguments fill all the expected parameters, apply the function to them, otherwise wait for remaining arguments.

Remember these two steps.

Curry function with named parameters

The idea is to apply the approach described above and make auto curried version of NPF in JavaScript. The advantage of a curried NPF is that now you can not rely on parameter’s order while partially applying it.

What to expect?

How to achieve the first step and get function’s parameter list? Let me reinvent the wheel:

Here is a pipeline from the bottom up:

  1. Get string representation of a function;
  2. Extract parameters definition from the string;
  3. Extract individual parameters’ names into a list by regexp.

You can easily get the parameter list of a basic function (without destructuring and rest parameters):

The problem of JS implementation of NPF is that it has only the one real parameter — object with keys as parameter’s names. This is because there is no native support for a function with parameter destructuring in browsers and Node.js and the only alternative, Babel, converts parameter destructuring into a single parameter:

If you try to get the parameter list of this function using params() you will get the list with a single element: ['_ref'].

There are two workarounds:

  1. Create and manage a list with parameters manually for every NPF (pretty straightforward);
  2. Get the parameter list while converting PPF into NPF.

The second way needs to be discussed. The following function performs required transformation:

Function ppf2npf() accepts PPF and returns a function which expects an object as a collection of arguments, nps (for 'named parameters'). The advantage of this method is that it allows you to retrieve the list of parameters procedurally from PPF, which you can use to curry obtained NPF. As you see it uses params() function, so you can convert only basic PPF (without default values and rest parameters). This is a disadvantage.

Are given arguments expected?

The second part of the general currying idea could be expressed as the following function:

  1. Function npfCurry() accepts a list of expected parameters, a function npf which it will curry, and an acc list of arguments passed to the previous npfCurry() call. In case of the first call the acc is empty by default.
    The function returns another function which will manage expected and given, paramsObj, arguments.
  2. The function firstly determines which of the given arguments match with the list of expected and stores it in the suited list. We don't need unexpected arguments.
  3. Then it merges suited arguments with ones received earlier into the $acc collection.
  4. Finally, it compares the set of suited arguments with the set of expected.
  5. Case of equality means that all expected arguments were passed and the time to apply npf() to them has come.
  6. Otherwise, the function calls itself recursively with already obtained arguments in the $acc and waits for remaining ones which are expected minus given.

Glue two parts

Now we have both mechanisms, one for getting parameter list, and another for currying NPF. The following function converts basic PPF into curried NPF:

If you already have NPF, create its parameter list manually and pass both to npfCurry():

Yeah, the first way requires the function to be a basic PPF, which isn’t always acceptable. The second case isn’t perfect too and violates DRY principle which causes need to manage parameter’s definition in two places: in the parameter list and in the NPF itself. But, by now I haven’t found another way to auto curry NPF.

Nevertheless we have reached the goal. Now we have auto curried NPF. Let’s test curriedNpfSearch() with our hackneyed functional example:

If you have any ideas how to achieve NPF currying more elegantly or you already know the way, I will be glad to discuss it with you!

Not an only JavaScript privilege

If you look at some functional programming languages you will find that the discussed feature has been already implemented. We are not pioneers.

Let’s try Haskell:

The same feature is available in OCaml, you can try it by yourself.

--

--

Dimitri Nikogosov
Webtips
Writer for

MD | Clinical geneticist | Bioinformatician | Functional programming enthusiast