Functional Programming: Alternatives to the IF #Functional #JavaScript #Functors
Tags: javascript, es6, functional, functors
Published: 2018-04-04 18:42:10

---
title: Functional Programming: Alternatives to the IF #Functional #JavaScript #Functors
published: true
description: 
tags: javascript, es6, functional, functors
---

A couple of times I have been asked "How would you do X in functional programming?" I absolutely love these types of questions.

I do my best to answer every question, but I think there are many questions interesting enough to warrant their own articles.

So for this article I would like to demonstrate how I could recreate this imperative function in a more functional manner.

This function has an `if` statement without an `else`. So while a `ternary` operator could work, it is not ideal.

```javascript
// A basic redux-thunk action that only dispatches when value exists
const someAction = value => dispatch => {
  const item = getItem(value)
  if (item != null) {
    dispatch({ type: 'ACTION', item })
  }
}
```

Here we need to run `dispatch` only when we have a `value`, otherwise we do nothing.

One option is to use a short circuit operator:

```javascript
// short circuit
const someAction = value => dispatch => {
  const item = getItem(value)
  item && dispatch({ type: 'ACTION', item })
}

// ternary
const someAction = value => dispatch => {
  const item = getItem(value)
  item ? dispatch({ type: 'ACTION', item }) : null
}
```

Short circuit and ternary and both ways you can solve this problem, but let's take a look at a couple more.

# Solution A: ifVal Helper Function

To do this in a more functional way, I will create a helper function. I'll write this helper old school first then boil it down piece by piece so everyone can understand it easily.

```javascript
// 1: old school
function ifVal (x, f) {
  if (x == null) {
    return null
  } else {
    return f(x)
  }
}

// 2: convert to arrow function
const ifVal = (x, f) => {
  if (x == null) {
    return null
  } else {
    return f(x)
  }
}

// 3: convert if/else to a ternary operator
const ifVal = (x, f) => {
  return x == null ? null : f(x)
}

// 4: voilà!
const ifVal = (x, f) => x == null ? null : f(x)
```

Now we can modify our `someAction` function to use `ifVal` instead of the classic `if` block.

```javascript
// functional alternative
const someAction = value => dispatch =>
  ifVal(getItem(value), item => dispatch({ type: 'ACTION', item }))
```

Here's the comparison for a quick and easy twitter screenshot:

```javascript
/**
 * execute the function if the value is not null or undefined
 * @param {Object} val - the value to test
 * @param {Function} fn - the function to execute.
 * @returns {Object} - null or the value of the executed function.
 */
const ifVal = (val, fn) => val == null ? null : fn(val)

// imperative example
const someAction = value => dispatch => {
  const item = getItem(value)
  if (item!= null) {
    dispatch({ type: 'ACTION', item })
  }
}

// functional example
const someAction = value => dispatch =>
  ifVal(getItem(value), item => dispatch({ type: 'ACTION', item }))
```

## Further reading

Take a look at Ramda's [when](http://ramdajs.com/docs/#when), [unless](http://ramdajs.com/docs/#unless), and [ifelse](http://ramdajs.com/docs/#ifElse) for other useful and similar functions.

# Solution B: Functors

We could also use the **Maybe Type**. The Maybe Type consists of either a `Just` type which holds a value or a `Nothing` type which is exactly what is says.

For this example, I'll use the Maybe Type from the [Sanctuary](https://sanctuary.js.org) library.

It looks a little like this:

```javascript
/* Examples of Sanctuary's Maybe */

toMaybe(null) //=> Nothing
toMaybe(undefined) //=> Nothing
toMaybe(0) //=> Just(0)
toMaybe(false) //=> Just(false)
toMaybe(123) //=> Just(123)
toMaybe({ name: 'joel' }) //=> Just({ name: 'joel' })
```

The Maybe Type is pretty simple and the reason why I want to use it is because `map` and `Maybe` work together so well, it was been given a special name, a **Functor**.

Some libraries like [ramda-fantasy](https://github.com/ramda/ramda-fantasy) have a fluent syntax, but this article is using Sanctuary. Though, it is good to know that these two are equivalent.

```javascript
const double = x => x * 2

// ramda-fantasy
Maybe.toMaybe(333).map(double) //=> Just(666)

// Sanctuary
map(double, toMaybe(333)) //=> Just(666)
```

Examples:

```javascript
const double = x => x * 2

// map is ignored
map(double, toMaybe(null)) //=> Nothing

// no more null exceptions!
map(val => val.something(), toMaybe(null)) //=> Nothing

// map is mapped
map(double, toMaybe(333)) //=> Just(666)
```

All together `doSomething` with the Maybe will look like this:

```javascript
import { toMaybe, map } from 'sanctuary'

const someAction = value => dispatch => {
  const item = getItem(value)
  const maybeValue = toMaybe(item)
  map(item => dispatch({ type: 'ACTION', item }))(maybeValue)
}
```

Here we have three functions, `getItem`, `toMaybe` and `map` that can be composed together into a new single function. We can pass value into that new function and it will flow through first into `getItem`, then `toMaybe` and finally that value will flow into our `map`.

```javascript
const someAction = value => dispatch => pipe([
  getItem,
  toMaybe,
  map(value => dispatch({ type: 'ACTION', value })),
], value)
```

And for one last picture perfect Tweet:

```javascript
import { toMaybe, map, pipe } from 'sanctuary'

// imperative example
const someAction = value => dispatch => {
  const item = getItem(value)
  if (item != null) {
    dispatch({ type: 'ACTION', item })
  }
}

// maybe functor example
const someAction = value => dispatch => pipe([
  getItem,
  toMaybe,
  map(value => dispatch({ type: 'ACTION', value })),
], value)

someAction(666)(dispatch) // Action is dispatched!
someAction(null)(dispatch) // Nothing happens
```

# End

I hope you enjoyed this small functional journey. Let me know in the comments if you did, if you got lost, if you have any questions, or if you want more articles like this one. If you really want to motivate me, follow me here or [Twitter](https://twitter.com/joelnet) and if you **loved** this article, pass it around!

Cheers!