Lenses and Partial-application
Tags: javascript, functional, partialapplication, lenses
Published: 2022-03-19 10:23:01

---
title: Lenses and Partial-application
published: true
description: Using partial-application to focus on object properties.
series: Going functional one step at a time
tags: javascript, functionalprogramming, partialapplication, lenses
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ujlv00ot4xw60yvewh6m.png
---

There is a concept from the Functional Programming camp known as lenses that can simplify accessing values (properties) in data structures (objects and arrays). Whilst not directly supported in JavaScript it can be implemented easily in a variety of ways and is an effect technique well worth learning.

To demonstrate the concept we will use another FP technique called partial-application to simplify the task of sorting arrays of objects. We will look at three methods of implementing partial-application. The first mechanism makes use of JS's `bind` method, second approach uses a closure and recursion. The third utilises the (dreaded) array `reduce` method.

###A short explanation of Partial-Application
In brief the technique of partial-application enables the programmer to supply arguments in stages and execute the function only once all of the required arguments have been supplied. This is in contrast to the more _conventional_ approach of supplying all the arguments at the same time and executing the function immediately. 

####Benefits of this technique
One of the benefits of this technique is that those parameters that do not change between calls can be supplied once whilst those than change on each call can be provided last minute.

Another, and probably more useful, benefit of this technique is we can effectively define two (or more) interfaces for the function. For example. An array's `map` method expects a transform function with the interface of `(item, index?, array?)` where item is each entry in the array, index (optional) is the subscript of the item in the array and array (again optional) is the array itself. We cannot supply additional parameters directly which can limit reuse of the function. Using partial-application we can create the transform function with the expected interface using another function that is supplied with additional arguments, which are in scope (and accessible) within the transform function. 

_Please add a comment below if you would like me to demonstrate this feature in another post but now back to the original topic._

###A refresher on sorting an array
The `Array` object has a method called `sort` that anticipates a comparison function used to arrange items in the array (see [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) for more details on `sort`). The function is called several times during the `sort` operation, requires two parameters and returns a numeric value according to the following rules:
* zero indicates the values are the same
* positive values indicate the items are in descending order
* negative values indicate the items are in ascending order 

Let's check out a simple example using a list of names (strings).

```javascript
const testData = ['Bob', 'Chris', 'Eve', 'Alice', 'Dave'];

testData.sort((person1, person2) => {
  if (person1 === person2) return 0;
  if (person1 > person2) return 1;
  return -1;
});

console.table(testData);

/* OUTPUT
┌─────────┬─────────┐
│ (index) │ Values  │
├─────────┼─────────┤
│    0    │ 'Alice' │
│    1    │  'Bob'  │
│    2    │ 'Chris' │
│    3    │ 'Dave'  │
│    4    │  'Eve'  │
└─────────┴─────────┘
*/
```

Now we will 'up the ante' by sorting an array of objects by a slightly nested property. 

```javascript
const testData = [
  { name: 'Chris', dob: { year: 1980, month: 2, day: 1 } },
  { name: 'Bob', dob: { year: 1980, month: 8, day: 5 } },
  { name: 'Eve', dob: { year: 1980, month: 4, day: 2 } },
  { name: 'Dave', dob: { year: 1980, month: 6, day: 4 } },
  { name: 'Alice', dob: { year: 1980, month: 4, day: 3 } },
];

testData.sort((person1, person2) =>
  if (person1.dob.month === person2.dob.month) return 0;
  if (person1.dob.month > person2.dob.month) return 1;
  return -1;
);

console.table(
  testData.map(person => ({
    name: person.name,
    month: person.dob.month,
    day: person.dob.day,
  }))
);

/* OUTPUT
┌─────────┬─────────┬───────┬─────┐
│ (index) │  name   │ month │ day │
├─────────┼─────────┼───────┼─────┤
│    0    │ 'Chris' │   2   │  1  │
│    1    │  'Eve'  │   4   │  2  │
│    2    │ 'Alice' │   4   │  3  │
│    3    │ 'Dave'  │   6   │  4  │
│    4    │  'Bob'  │   8   │  5  │
└─────────┴─────────┴───────┴─────┘
*/
```

Even with this relatively simple example the comparison function is starting to get a bit messy and repetitious (person_.dob.month). We can simplify it using a technique inspired by Functional Programming's lenses to access object properties. 

I this first attempt we create a function that requires one of the items from the array and returns the value of the property we want to sort by. In this example the syntax for the `sort` comparison is slightly different but the effect is the same. _See my note on this aspect towards the end of this post to find out more._

```javascript
function lookup(person) {
  return person['dob']['month'];
}

testData.sort(
  (person1, person2) =>
    -(lookup(person1) < lookup(person2)) ||
    +(lookup(person1) > lookup(person2))
);
```

####Using the JS `bind` method 
The above comparison function is cleaner and more dynamic but the `lookup` function just moves referencing of the property out of the comparison function and remains very specific. We can do better by creating a lens (aka `lookupGenerator` in the following examples) using partial-application. 

In the following example we will use the JS OO facility `bind` to apply, partially, `lookupGenerator` to create the `lookup` function.

```javascript
function lookupGenerator(prop1, prop2, obj) {
  return obj[prop1][prop2];
}

const lookup = lookupGenerator.bind(null, 'dob', 'month');
```
When the `lookupGenerator` function is called it is supplied with arguments to populate the first two properties `prop1` and `prop2` but not the third. Using the `bind` method returns a new function that is assigned to `lookup`. The new function only requires the third parameter to be supplied in order for the lens to operate. 

The `sort` operation does not change, supplying the lens with the specific items out of the array that require comparing. Not how we satisfied the parameters (partially-applied the arguments) of the lens in two stages with the second being within the sort comparison function. 

####Using JS closure and recursion 
The `lookupGenerator` is still rather specific so here is another way of implementing a lens through partial-application using a closure, recursion along with rest and spread operations. This approach is more complicated but is far more dynamic and reusable.

```javascript
function lookupGenerator(...props) {

  const _lookupGenerator = (obj, prop, ...props) =>
    prop ? _lookupGenerator(obj[prop], ...props) : obj;

  return obj => _lookupGenerator(obj, ...props);
}

const lookup = lookupGenerator('dob', 'month');
```

In the above implementation of the `lookupGenerator` lens we start by providing all of the properties (in sequence) required to locate the property we want to sort by but this time there can be any number of arguments and they are defined by the use case not implementation. The recursive process keeps calling `_lookupGenerator` until all the supplied parameters are exhausted before returning a function to accept the final argument (the object) and execute the function to retrieve the value of the property within it. 

####Using the Array `reduce` method
The third and final approach might be shorter but the fact it uses the Array `reduce` method can make it appear more complicated. However, all that is happening here is the array on which the `reduce` is being performed is the list of properties for the object lens. 
The starting value of the accumulator is the object in focus. It still employs partial-application because the list of properties is passed on the first call, a function is returned. When the generated function is called it is passed the subject object and (if found) returns the value of the property. 

```javascript
function lookupGenerator(...props) {
  return obj =>
    props.reduce((o, p) => 
      p in o ? o[p] : null, obj);
}
```

The last two examples (above) have the advantage that the generator can be reused and supplied with a variety of arguments. For instance we can even reference array subscripts as follows.

```javascript
const dayOfFourth = lookupGenerator('3', 'dob', 'day');

console.log(dayOfFourth(testData));

// Fourth entry is 'Dave' with a day of birth of '4'
``` 

###Conclusion
While this `sort` example is rather simplistic I think it demonstrates adequately how lenses can simplify code such as the comparison function but providing a mechanism for locating properties deeply nested in objects and arrays. 

Using the `bind` method to create the lens demonstrates the concept but is rather limiting and specific (not reusable.) The recursive and reduce approaches might be more difficult to understand but are far more reusable. 

The code illustrated in this post is not recommended for use in production but the concepts most certainly are. Libraries like [lodash](https://lodash.com/) and [underscope](https://underscorejs.org/) provide many tried and tested, production-ready functions, some from the FP camp, that can simplify your code and make it easier to create reusable code.

####Finally, a note on the comparison function (I did promise)
Whilst writing this post I found I could write the comparison function as follows.

```
(person1, person2) =>
  -(person1 < person2) || +(person1 > person2)
```

This is a technique I have not seen anywhere else and not used before myself, so I conducted some additional testing and found it worked. However, I am sure there are undiscovered pros and cons. There is a mix here of Boolean logic, (lazy) numeric evaluation and type coercion that TypeScript might object to but is sound JS.

#####How it works
The Boolean values `true` and `false` coerce to numeric values 1 and 0 respectively, so the numeric comparisons (less than and greater than) will first return a Boolean value before being converted to numeric values -1|0 and +1|0 respectively.

The logical `or` (`||`) performs lazy evaluation so if the two values being compared are in (less than) order the second (greater than) expression will not be performed and -1 will be return immediately. If the values being compared are equal both sides will result in 0 and zero will be returned (not false as might be suspected).

Supporting code for this post can be found at [JSFiddle](https://jsfiddle.net/TGJGilmore/L2tvuyog/) including some proof tests for my comparison function.

###Supplemental

There is a [supplementary post](https://dev.to/tracygjg/fp-lenses-enhanced-going-functional-one-step-at-a-time-4cp7) to this to describe an enhancement to the code.