Practical Functional Programming in JavaScript - Control Flow
Published: 2020-07-23 19:21:54

Usually when authors use the terms "functional programming" and "control flow" together in the same sentence, it's to say functional programming should not have control flow.
 * "Chapter 1. (Avoiding) Flow Control" - [Functional Programming in Python](https://www.oreilly.com/library/view/functional-programming-in/9781492048633/ch01.html)
 * "Destroy All Ifs" - [A Perspective from Functional Programming](https://degoes.net/articles/destroy-all-ifs)
 * "More precisely, in true functional programming, there is no control flow." - [Functional Programming in JavaScript, Part 1: The Unit](https://marmelab.com/blog/2018/03/14/functional-programming-1-unit-of-code.html)

I'm using the [wikipedia definition](https://en.wikipedia.org/wiki/Control_flow) for control flow in this case
> control flow (or flow of control) is the order in which individual statements, instructions or function calls of an imperative program are executed or evaluated

Control flow explicitly refers to **statements**, which are different from **expressions**. Where JavaScript is concerned, statements have semicolons and expressions do not. This is an important distinction, and means the difference between imperative and functional programming in JavaScript.

```javascript
a + b;
// a, b and a + b are expressions
// a + b; is a statement
```

All of the articles above avoid `if` statements and instead prefer language equivalents of the [conditional (ternary) operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator). I'm here to agree with them in technicality and diverge a bit in practice. I diverge because the conditional operator can get messy in practice; I'm here to offer a cleaner, more scalable way. More on this later on.

The conditional (also referred to as "ternary") operator takes three operands: a condition expression, an expression to evaluate on truthy condition, and an expression to evaluate on falsy condition. It's like `if` and `else`, but instead of statements (yes semicolons), you put expressions (no semicolons).

```javascript
condition ? a : b // if condition, evaluate expression a, else evaluate expression b
```

Purely functional languages like Haskell don't have the notion of a semicolon; they rely on syntax resembling the conditional operator

```haskell
if condition then a else b
```

Python also has conditional-like syntax
```python
a if condition else b
```

As you can see, the concept of a "ternary", or that which is "composed of three parts", is common across languages. It just makes a ton of sense to express a choice with three things: if some condition, do this, else do that. With JavaScript, you can do this imperatively with `if`, `else` statements or functionally with the conditional operator.

```javascript
// imperative
const describeNumber = number => {
  let description = '';
  if (number < 0) {
    description = 'negative';
  } else if (number === 0) {
    description = 'zero';
  } else {
    description = 'positive';
  }
  return description;
};

// functional
const describeNumber = number =>
  number < 0 ? 'negative'
  : number === 0 ? 'zero'
  : 'positive';
```

You can go pretty far with the conditional operator alone, but there will be times when something more expressive could help you solve your problems better. This is especially true for code with a lot of branching or complex data handling. For these cases, I've devised a clean and declarative way for you to express conditional flow with my functional programming library, [rubico](https://github.com/a-synchronous/rubico).

Consider an entrypoint to a basic node command line interface application that accepts flags. The application is very simple; all it does is print its own version and its usage.
```javascript
// argv [string] => ()
const cli = argv => {
  if (argv.includes('-h') || argv.includes('--help')) {
    console.log('usage: ./cli [-h] [--help] [-v] [--version]');
  } else if (argv.includes('-v') || argv.includes('--version')) {
    console.log('v0.0.1');
  } else {
    console.log('unrecognized command');
  };
};

cli(process.argv); // runs when the cli command is run
```

This is nice and familiar, but it's imperative, and you're here about functional programming, after all. Let's refactor some functionality and use the conditional operator.
```javascript
// flag string => argv [string] => boolean
const hasFlag = flag => argv => argv.includes(flag);

const USAGE = 'usage: ./cli [-h] [--help] [-v] [--version]';

// argv [string] => ()
const cli = argv =>
  hasFlag('--help')(argv) || hasFlag('-h')(argv) ? console.log(USAGE)
  : hasFlag('--version')(argv) || hasFlag('-v')(argv) ? console.log('v0.0.1')
  : console.log('unrecognized command');

cli(process.argv); // runs when the cli command is run
```

Now it's looking real cool, but don't you think there's a lot of `argv`s everywhere? It gets better with rubico.
 * [switchCase](https://doc.rubico.land/#switchCase) - like the conditional operator, but with functions. Each function is called with the same input
 * [or](https://doc.rubico.land/#or) - like the logical or (`||`) operator, but with functions. Each function is called with the same input

```javascript
const { or, switchCase } = require('rubico');

// flag string => argv [string] => boolean
const hasFlag = flag => argv => argv.includes(flag);

const USAGE = 'usage: ./cli [-h] [--help] [-v] [--version]';

const log = message => () => console.log(message);

// argv [string] => ()
const cli = switchCase([
  or([
    hasFlag('--help'),
    hasFlag('-h'),
  ]), log(USAGE),
  or([
    hasFlag('--version'),
    hasFlag('-v'),
  ]), log('v0.0.1'),
  log('unrecognized command'),
]);

cli(process.argv); // runs when the cli command is run
```

With `switchCase` and higher order logical functions like `or`, it's like you're just typing it as you're thinking it. If the argv has the flag --help or -h, print the usage. Otherwise, if it has the flag --version or -v, print the version v0.0.1. Otherwise, print unrecognized command. I think it's an intuitive way to go about expressing logic in functional programs.

My hope is with `switchCase` and the logical combining functions `and`, `or`, and `not`, we could have a good basis to scale conditional expressions in functional JavaScript beyond the conditional (ternary) operator. If you have any thoughts about this or anything, I would love to get back to you in the comments. Thank you for reading! I'll see you next time on _Practical Functional Programming in JavaScript - Error Handling_

You can find the rest of the series in rubico's [awesome resources](https://github.com/a-synchronous/rubico/#awesome-resources)

Sources:
 * https://en.wikibooks.org/wiki/Haskell/Control_structures
 * https://www.w3schools.com/js/js_statements.asp
 * https://stackoverflow.com/questions/394809/does-python-have-a-ternary-conditional-operator