Dealing with collections in functional way.
Published: 2023-11-19 20:15:36

If there is a domain where functional programming (FP) shines, it's when dealing with lists, collections, arrays of objects.
Lisp is certainly the best prove of it.

Let's see how FP can help us with a simple example.

Suppose we have the following object :

```js
let pets = [
  {
    petname : "Bill",
    breed : "poodle",
    weight: 12,
    owner : {
      ownername : "Paul",
      contribution : {
        amount : 32,
        payed : false
      },
      address : {
        city :  "Paris"
      }
    }
  },
  {
    petname : "Maya",
    race : "pointer",
    weight: 27,
    owner : {
      ownername : "Henri",
      contribution :  {
        amount : 12,
        payed : true
      },
      address : {
         city :  "London"
      }
    }
  },
  {
    petname : "Ooper",
    race : "setter",
    weight: 20,
    owner : {
      ownername : "Nicolas",
      contribution :  {
        amount : 12,
        payed : true
      },
      address : {
         city :  "London"
      }
    }
  }
]
```
The goal is to retieve, the owner's name and corresponding pet names where the property **payed** is true;

To accomplish our goal we will need a few helpers in our toolbox :

```js

const pickprop = (prop) => (obj) => !!obj[prop] ? obj[prop] : false;

const map = (f) => (arr) => arr.map(f);

const filter = (f) => (arr) => arr.filter(f);

const pipe = (...fns) => initial =>  { return fns.reduce((acc, f) => f(acc), initial) };

```
The only tricky function is the **pipe** function.

**pipe** takes a list of functions, and iteratively 'feed' every function with the result of the previous function call.
The computation starts when the initial value is passed.

With those tools at our disposal, let's declare some constants, which are in fact functions.


```js
const tap = (p) => {console.log(p); return p;}

const owner = pickprop("owner");
const petname =  pickprop("petname")
const contribution = pickprop("contribution");
const payed = pickprop("payed");

const ownerpayed =  pipe(owner, contribution, payed)
const ownername = pipe(owner, pickprop("ownername"))

```
Notice how we can access fluently the properties of the object without relying in ugly 'dot' notation.

Here is the 'business part' :-)

```js

const filterpayed = filter(ownerpayed);

```

Here the presentation part : 

```js

const ownerandpet = map(p => ({owner: ownername(p), petname : petname(p)}));

```

Here the main part :

```js

let main = pipe ( 
    filterpayed 
  , ownerandpet
);

```

Finaly we can execute our main function :

```js

console.log (main(pets))

```

The final result is :

```js

[ { owner: 'Henri', petname: 'Maya' }, { owner: 'Nicolas', petname: 'Ooper' } ]

```

A step further :

```js

const filterownerpayed = filter(p => ownerpayed(p) == true);
const filterstayinlondon = filter(p => ownercity(p) == "London")
const ownerandpet = map(p => ({owner: ownername(p), petname : petname(p)}));

let main = pipe ( 
    filterownerpayed 
  , filterstayinlondon
  , tap
  , ownerandpet
);

```


 

The beauty of this, is that all our filters functions are testable, and you can put any 'middleware' in the **main** function.

You can for example insert the **tap** function anywhere in the chain.


You can of course stick with the traditional way :

```js

let main = function (pets) {
  return pets
    .filter(p => p.owner.contribution.payed)
    .filter(p => p.owner.address.city == "London")
    .map(p => ({owner: p.owner.ownername, petname : p.petname}) )
}

```

Hope you enjoyed.


You can play with the [demo](https://flems.io/#0=N4IgtglgJlA2CmIBcAOAbAOgExoDQgDMIEBnZAbVADsBDMRJEDACwBcxYR8BjAeytbwByECAC+uanQYhm8WAAd4AJxIYAVmR79BwxgB0qhgPQAqQ3yolWAAkM2bCiNwDWS1rXo2AvI+dvlXgUACn0Qd094MIBKQ1w-VwAjZXh4KBIfBICg0JBk1KgYuKzeAHcqFUynVwVAkLCyiuUiqnjqlxoYFJIM33banLDOqG6SFrb-S1ZlCESAV1YIfir-AfqQKZn5xf5xrLpeOYEVmrrcg6PWPfbGlUiT7PXb5UjryYhWAE8HtdzuD8+bxqNE+aR+ZzCChBaRaFn41jsVAcz3ufQgShswRu5RUE1cKOksVajngHmkP1Jr2JUNBUB+0MKxOezBoJBpYLRGKx-meeJcm1mCyW1NWDOiAG5DHCrLZngAFEH0Y6+AhHbg7JFY0nRGzAew2FKsOYvXX65E45Q2JA2An0LWsaLxM2OBlWm0Wllshn2x3OiLk63+u3uIkOMSGcNGCoADwUvGUtmALtp8XliqErDEiNMxilVC4IBI8ng6uFZEYAEYkAAGcSSECREQaLQbHQZkR5hC2dy9GzkfV6pEOElkrzWsIAIWIsDCuGd+TB4-CvF4cCiXGdpXgEAA5mxrRWsHOh+amm7B8Ph7b4G6wgq5jONyfhwLtsLz87LxdjtaAMxHz9h3ZOlrQIGhYCLQCJEA4ZRg-Z9L3+L43TsEAFRmMYQCg51IzDY8HAvIDKQDVCAFkQRoWdnWUGhuBvJc4wgAQVCo58t13fcbCwAB2fCrwteDL1PO4SLCAAJIQZlYoSbFfIVlmtU0EOHb9bAPADlIcYC3WmOYomU6DlNg+AekEmSHCQ75FLCAAZfgoF2LCDJw-VDIIv1iLHVCAHkghYp9Lxoujb0LUlBGaALh3YvdWGtLBqz44TLWtQjL2vEKADlnF4WBWWkoS5I1FDUqE1S3UPRKhO061dP0mS3NKroTIyFLAJfAEUNs+zHOw59cJsSMAF080sBEnAxXxggwaaCCsHVvAAPhsJiPggcCfCW3UDVJY0kVmtQUigOY6OCYJaO4eICHmpaCDO7huEdZaqFW8CdTESUqFG7tVjqTIsTqa7MV4RJ1EBgBCMHgfUcg1kGmwAH4bRBmG6jh0DwKLD6vpsMAaAUP6ro2zEaGUZRAZJ5QMFxkIrqx+FbCIWBwoJwGztJ8nSYwRnwuCWm82lBFWDxv6FGiRbgFGnL4AwWBeB3LEJW2o0TQUcVIwF2UBLRU5BhAZ4YjpmUR1RLSft1oN1yJbHCvfbXHj+HQtnkowQAlDXkw5LJfkhBkDZG+n3SabTfD8JRgl5WTHcFDU2jFd30s5eBw4tPlvb1i1Xldol3e5lRg5sXPlGToOxUNhFnhoKgoHcTJqaxIngmAZ5rWvBW2k8+jjekBWxGiN2oy7HGaCYlYuURS9C+0-VUwtSvq9JQx+4FqWZblzFcaY+0SD7-mo13-f83wIsEFLeERCrWsJCkegm24HoCymdtGHEQb8EbRgAGFjWUT4sHEIA)