Partial Application and Parameter Ordering
Tags: functional, clojure, programming
Published: 2022-11-14 19:21:35

## Introduction

Something that often is given little consideration is the order of function parameters. Admittedly, frequently it doesn't make that a whole lot of a difference, but sometimes, specific parameter ordering can make our life easier.

⚠️This blog uses Clojure for its examples. I think Clojure's terseness is helpful in making good examples. If you don't know Clojure at all, check out my [Very Short Introduction to Clojure](https://dev.to/jdurstberger/a-very-short-introduction-to-clojure-43bf).⚠️

Let's consider a function that adds value add tax (VAT) to a priced item. In a lot of countries, VAT differs between different types of products. We can easily encode this information in a map.

```clojure
(def vat-percentages
  {:food-item 10
   :culture   13
   :default   20})
```

Our function `add-vat` needs two arguments, `vat-percentages` and a `product` that needs to be priced. Therefore there are two ways to order the function parameters.

```clojure
(defn add-vat
  [product vat-percentages]
  ...)

(defn add-vat
  [vat-percentages product]
  ...)
```

At first, both options seem viable, but things get a bit more interesting when we use `map` to price a collection of products.

A primitive implementation that uses an anonymous function, would make the two options still seem pretty equal.

```Clojure
(map (fn [product] (add-vat product vat-percentages))
     products)

(map (fn [product] (add-vat vat-percentages product))
     products)
```

But this approach doesn't leverage the whole toolkit of functional programming.

## Partial Application

An underused tool is partial application.
Partial application allows us to take a function with arguments and pre-fill some of those arguments so we end up with a function that requires less arguments.

This can be demonstrated nicely with the `+` function.

```clojure
;normal usage
(+ 2 3) ;=> 5

;partial application
(def add-3 (partial + 3))

(add-3 2) ;=>5
(add-3 9) ;=>12
```

`partial` returns a new function which has 3 'baked in' as one of the arguments. We then assign the returned function to a new symbol `add-3` as to be able to easily refer to it.

Looking back at the previous implementation of our `map` invocation we see now that we could try to leverage `partial` to pre-fill the tax information on our `add-vat` function.

The only consideration with `partial` is that arguments are "pre-filled" left-to-right.
This means that if we want to use partial on our `add-vat` function we have to put the `vat-precentages` before `product`.

Let's try it on our VAT example.

```clojure
(def vat-percentages
  {:food-item 10
   :culture   13
   :default   20})

(defn add-vat
  [vat-percentages product]
  ...)

(defn apply-vat 
  [vat-percentages products]
    (map (partial add-vat vat-percentages) products))
```

Compare this to the previous example.

```clojure
(defn apply-vat 
  [vat-percentages products]
    (map (fn [product] (add-vat vat-percentages product)  products))
```

It might not make a huge difference but it declutters our code and leaves only what's important.
This is just a short example but it shows that parameter ordering makes a difference and enables us to use more tools from our toolkit.

## Creating a Heuristic

From experience I have found that ordering parameters from more to less stable works quite well.
What I mean with stable is how likely it is that the value of the argument changes between invocations.

In the above example `vat-precentages` changes less often than the `product` that we are pricing.

Another example might help clarifying this way or thinking.
Let's consider a function that makes a network call.
The function requires a logger, a base-url of the api, a token, and then a payload to post.

Using the above technique most likely leads us towards something like this.

```clojure
(defn post-to-api
  [logger base-url token payload]
  ...)
```

When the system starts we could use `partial` to pre-fill `logger` and `base-url`. Once a user has authenticated we could use `partial` again to pre-fill `token`.

We are then left with a function that only requires a payload and puts little burden on the callee.

## Conclusion

Partial application is a powerful tool to make your code more terse and can also be used to abstract required arguments from code further down.
To fully leverage partial application we should order function parameters from most to least stable.

Maybe you give it a go and let me know what you think?