Imperative vs Declarative
## To begin...
Imagine a simple todo list spec...
* List of items
* Cross off item when clicked
* Count of done/total at bottom
## Imperative UI with jQuery
* HTML containers
* Add line items
* Update as needed
* Counts
* "Completed" state
[Example](http://codepen.io/jetpacmonkey/pen/JbbaEE)
## New specs!

* Progress bar
* Say "done" when all are checked off
* Filter by done/todo/all
* Filter by search text

## Changes
* Every time a todo is added/changed
* Update progress bar
* Update "done" state
* When filter link is clicked, or search text is entered
* Hide/show items
* Update counts
* Update progress bar
* Update "done" state
Everything has to be kept in sync
Every possible permutation has to be coded for
What about searching within a filtered list?
What about the next feature request?
## Issues with directly mutating UI
* Related data needs to manually be synchronized
* Difficult to be modular
* Subsequent changes grow complexity exponentially
There's a better way...
## Declarative UI with React
* Store todos as data
* Direct mapping of data to elements
* Update stored state, not the elements themselves
[Example](http://codepen.io/jetpacmonkey/pen/gLLdeB?editors=0110)
## Tradeoffs?
* ~100 lines vs ~50
* More library overhead
* Questionable for such a simple app
Let's see how well it handles that spec change...
[Example](http://codepen.io/jetpacmonkey/pen/QGGVXw?editors=0110)
## Key Benefits
* Child components don't know about each other (loose coupling)
* Separation of data from presentation
* New features don't have to change old ones
* Dev doesn't have to keep track of every possible code path

With a declarative style, we tell the machine what result we want,
not how to get there.
So how else can we be more declarative?
## Functional programming
We saw declarative UI, now let's look at a more declarative style for
functions themselves.
Functional programming, at its most basic, is defining everything in
terms of simple 1-to-1 transformations, with consistent outputs for
consistent inputs.
Some tools to help us define relationships more easily...
## Currying
Allows the programmer to only partially fill in the arguments of a
function, defining another function that takes the rest.
```
threeWords(a, b, c) {
return a + ' ' + b + ' ' + c;
}
twoWords = threeWords('hey'); // function that takes b and c
oneWord = twoWords('there'); // function that takes c
oneWord('world'); // 'hey there world'
```
## A more practical currying example
```
map(fn, arr) {
acc = [];
for (var i=0; i < arr.length; ++i) {
acc.push(fn(acc[i]));
}
return acc;
}
allPrices = map(item => item.price);
allPrices([{ price: 3 }, { price: 3.5 }]) // => [3, 3.5]
```
## Functional Composition
Combines functions together, so the result of one becomes the input
of the other.
`compose(f, g)(x) === f(g(x))`
Front-end team usually uses `_.flow`, which is the same thing
reversed.
`_.flow(f, g)(x) === g(f(x))`
Or, the way my mind tends to parse it...
```
tmp = f(x)
return g(tmp)
```
## Composition Example
```
min(arr) {
lowest = arr[0];
for (var i=1; i < arr.length; ++i) {
if (arr[i] < lowest) {
lowest = arr[i];
}
}
return lowest;
}
lowestPrice = _.flow(allPrices, min);
lowestPrice([{ price: 3 }, { price: 3.5 }]) // => 3
```
## Now let's look at that example again...
```javascript
const getLowestRegularShowtimePrice = _.flow(
fp.filter(hasRegularTickets),
fp.map(_.flow(
fp.get('regularTicketSections'),
fp.map('price'),
fp.min
)),
fp.min
);
```
## Some benefits of a functional, declarative style
* Modular
* Reusable
* Easily testable
* Easy memoization
## Summary
* Declarative style gives consistent, extensible code
* Currying gives convenient function factories
* Composition turns functions into building blocks
* FP is basically unicorn farts
Discussion!