An open API service indexing awesome lists of open source software.

https://github.com/jschomay/functional-programming-introduction

A light introduction to functional programming, with examples in ramda.js. View presentation at http://jschomay.github.io/functional-programming-introduction
https://github.com/jschomay/functional-programming-introduction

Last synced: 3 months ago
JSON representation

A light introduction to functional programming, with examples in ramda.js. View presentation at http://jschomay.github.io/functional-programming-introduction

Awesome Lists containing this project

README

        

A light introduction to
Functional Programming
==============================

`k => {k: v} => {k: v} => Boolean`

What is FP?
-----------

- A focus on functions as the basic building block
- Functions that take other functions as arguments
- Functions that return other functions
- Pure
- Same inputs give the same outputs (don't rely on outside state)
- No side-effects! (mutating state, calling other api's)

Why FP?
--------

- Robust - predictable, flexible, and less buggy
- Easy to read and reason about - "What" not "how"
- Separate behavior from data
- Build complexity through composition of simple, reusable units

Under the hood
--------------------

### Common examples

- `map`
- `bind` (aka `partial`)

### `Map`

```
function map (fn, list) {
let results = [];
for (let i = 0; i < list.length; i++) {
results.push(fn(list[i], i));
}
return results;
}
```

### Benefits
- Lets us focus on concepts ("map", "filter", "reduce") rather than implementation

```
let cardinalDegs = [0, 90, 180, 360];
let cardinalRads = map(MathLib.degToRad, cardinalDegs);
```

### `Partial`

```
function partial (fn, ...boundArgs) {
return (...calledArgs) => {
return fn.apply(null, [...boundArgs, ...calledArgs]);
};
}
```

### Benefits
- Lets us build up reusable behavior
- Separates defining behavior from applying our data

```
let getProp = (prop, obj) => obj[prop];
let getAge = partial(getProp, 'age');
let getAges = partial(map, getAge);

let people = [
{name: "Joe", age: 31},
{name: "Jack", age: 32},
{name: "Jim", age: 29}
];
let ages = getAges(people);
```

FP in practice
--------------
(with good ol' javascript)

### [Ramda.js](http://ramdajs.com/0.18.0/index.html)

![ramda](http://ramda.jcphillipps.com/logo/ramdaFilled_200x235.png)

- Practical and performant
- Supports and encourages composition
- Data last!
- Auto-curried
- [Hey Underscore, You're Doing It Wrong!](https://www.youtube.com/watch?v=m3svKOdZijA)

Composition
-----------

- Passing the output of one function as the argument for another
- Like unix's `pipe`

```
let fgh = (x) => {
f(g(h(x)));
};
fgx(x);
```

### With ramda

```
let fgh = R.compose(f,g,h);
fgh(x);
```

(pro tip - read from right to left, bottom to top)

Bonus points for being "points-free"

- Function definitions do not identify the arguments (or "points") on which they operate
- In other words, you don't see the `(...) => {...}` syntax (less clutter)

Currying
--------

- The ability to call a function one argument at a time
- Like partial application, but repeatable

```
let add3Things = (a, b, c) => a + b + c ;
let six = add3Things(1, 2, 3);

let curriedAdd3Things = R.curry(add3Things);

let six = curriedAdd3Things(1)(2)(3);
// or
let onePlusTwoMoreThings = curriedAdd3Things(1);
let threePlusOneMoreThing = onePlusTwoMoreThings(2);
let six = threePlusOneMoreThing(3);
```

A practical example
-------------------

```
let people = [
{name: "Joe", age: 31},
{name: "Jack", age: 32},
{name: "Jim", age: 29}
];

let getAges = R.map(R.prop('age')):
let ages = getAges(people); // [31, 32, 29]
```

What is the oldest age?
```
let getOldest = R.compose(R.max, getAges);
let oldest = getOldest(people); // 32
```

Who is under 30?
```
let isUnder30 = R.compose(R.gt(30), R.prop('age'));
let peopleUnder30 = R.compose(
R.map(R.prop('name')),
R.filter(isUnder30)
)(people); // ['Jim']
```

FP notation
-----------

So what does this mean:

`k => {k: v} => {k: v} => Boolean`

A function that takes a key, then one object, then another object, and returns a boolean.

Aka `R.eqProps` - Do two objects have the same value for a given key?

Now go play!
-----------
http://ramdajs.com/repl/