* Functional

# We use JS because it is everywhere

## Dr. Gleb Bahmutov PhD

Node, C++, C#,

Angular, Vue.js, React, server-side etc.

## work: Kensho

event analysis and statistics for financial markets

Boston and New York

## Problem: code complexity is quickly growing

number of engineers

lifetime of the company

# then most likely it will work

const todos = getTodos()
const updatedTodos = addNewTodo(todos, newTodo)
saveTodos(updatedTodos)

where does it get the data?

how does it save the data?

is this object modified?

const todos = getTodos()
const updatedTodos = addNewTodo(todos, newTodo)
saveTodos(updatedTodos)

what if getTodos() is called again

while the first save is still executing?

const todos = getTodos()
const updatedTodos = addNewTodo(todos, newTodo)
saveTodos(updatedTodos)

## We need JavaScript to

• be as clear as writing an English sentence (or clearer)
• produce expected result
• be simple to test
• assemble complex logic from very simple parts

Everyone has their own path to JS

# Fun 1

var numbers = [3, 2, 8]
var constant = 2
// 4 16

Problem: given an array of numbers, multiply even values by a constant and print the result

Write a solution using a for loop

# Imperative solution

var numbers = [3, 2, 8]
var constant = 2
var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (numbers[k] % 2 === 0) {
console.log(numbers[k] * constant)
}
}

We command the computer to iterate through the list of numbers

# What does this code do?

var numbers = [3, 2, 8]
var constant = 2
var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (numbers[k] % 2 === 0) {
console.log(numbers[k] * constant)
}
}

# Too many moving parts

var numbers = [3, 2, 8]
var constant = 2
var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (numbers[k] % 2 === 0) {
console.log(numbers[k] * constant)
}
}

for loop at some point will betray you

# 4 actions (not counting the variables!)

var numbers = [3, 2, 8]
var constant = 2
var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (numbers[k] % 2 === 0) {
console.log(numbers[k] * constant)
}
}

# Fun 2

var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (numbers[k] % 2 === 0) {
console.log(numbers[k] * constant)
}
}

Problem: extract functions that can be described with a single sentence

function mul(a, b) {
return a * b
}
function print(x) {
console.log(x)
}
function isEven(x) {
return x % 2 === 0
}
for (k = 0; k < numbers.length; k += 1) {
if (isEven(numbers[k])) {
print(mul(numbers[k], constant))
}
}

multiplies two numbers

prints one argument

returns true if x is even

var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (numbers[k] % 2 === 0) {
console.log(numbers[k] * constant)
}
}
function mul(a, b) {
return a * b
}
function print(x) {
console.log(x)
}
function isEven(x) {
return x % 2 === 0
}
for (k = 0; k < numbers.length; k += 1) {
if (isEven(numbers[k])) {
print(mul(numbers[k], constant))
}
}

Hmm, did we just blow up the size of the code for no reason?

# Atomization

initial spaghetti code

mul
print
isEven
...

"atoms"

compare: multiply even numbers by a constant

if (numbers[k] % 2 === 0) {
console.log(numbers[k] * constant)
}
if (isEven(numbers[k])) {
print(mul(numbers[k], constant))
}

almost reads like the problem itself

# Fun 3

function mul(a, b) {
return a * b
}
function print(x) {
console.log(x)
}
function isEven(x) {
return x % 2 === 0
}

Problem: which function is NOT like the other two?

hint: look where the variables are coming from

# Fun 3

function mul(a, b) {
return a * b
}
function print(x) {
console.log(x)
}
function isEven(x) {
return x % 2 === 0
}

Problem: which function is NOT like the other two?

# Pure functions

function mul(a, b) {
return a * b
}

only uses its arguments

same arguments => same result

does not modify the outside environment

# Impure functions

function print(x) {
console.log(x)
}

uses outside variable

modifies the outside environment

# Lexical scope

function mulBy(K) {
return function (x) {
return K * x
}
}

# Higher order functions

function mulBy(K) {
return function (x) {
return K * x
}
}

# Pure function can return non-pure function

function mulBy(K) {
return function (x) {
return K * x
}
}

pure

impure

# Function's source code

function mulBy(K) {
return function (x) {
return K * x
}
}
const double = mulBy(2)
console.log(double.toString())
// function (x) {
//   return K * x
// }

# Function's source code

function mulBy(K) {
return function (x) {
return K * x
}
}
const double = mulBy(2)
/*
double is same as
K = 2
function (x) {
return K * x
}
*/

# Fun 4

function mul(a, b) {
return a * b
}
const constant = 2
for (...) {
mul(constant, numbers[k]))
}

## Use known values early

function and one argument are known early

# Fun 4

function mul(a, b) {
return a * b
}
function mulBy = /* something here */;
var constant = 2
var byConstant = mulBy(constant)
for (...) {
byConstant(numbers[k])
}

# Return a function

function mul(a, b) {
return a * b
}
function mulBy(K) {
return function(x) {
return mul(K, x)
}
}
const constant = 2
const byConstant = mulBy(constant)
for (...) {
byConstant(numbers[k])
}

# Arrow function

function mul(a, b) {
return a * b
}
const mulBy = K => x => mul(K, x)
const constant = 2
const byConstant = mulBy(constant)
for (...) {
byConstant(numbers[k])
}

# Reuse existing functions

function mul(a, b) {
return a * b
}
const mulBy = K => x => mul(K, x)
const constant = 2
const byConstant = mulBy(constant)
for (...) {
byConstant(numbers[k])
}

# Referential transparency

function mul(a, b) {
return a * b
}
const mulBy = K => x => K * x
const constant = 2
const byConstant = mulBy(constant)
for (...) {
byConstant(numbers[k])
}

# Fun 5

const mulBy = K => x => K * x
const double = mulBy(2)
console.log(double.toString())
// x => K * x

## problem: change the value of K

hint: "eval" uses current lexical scope

// >>> insert statement here <<<
const triple
= eval('(' + double.toString() + ')')
console.log(triple(10))
// 30

# Fun 5

K = 3
// eval('(' + double.toString() + ')')
const triple = eval('(x => K * x)')
console.log(triple(10))
// 30

# Fun 6

function mul(a, b) {
return a * b
}
const constant = 2
const byConstant = /* something here */

## problem: bind known argument value without writing new function

hint: look at Function.prototype.bind

# Fun 6

function mul(a, b) {
return a * b
}
const constant = 2
const byConstant = mul.bind(null, constant)
// byConstant(10) = 20
// byConstant(-1) = -2

# Partial application

function mul(a, b) {
return a * b
}
const constant = 2
const byConstant = mul.bind(null, constant)

# Function signature design

## Place on the left arguments most likely to be known early

// vs
return {
deleteAccount: ...
}
}
function mul(a, b) {
return a * b
}
function print(x) {
console.log(x)
}
function isEven(x) {
return x % 2 === 0
}
const byConstant = mul.bind(null, constant)
var k
for (k = 0; k < numbers.length; k += 1) {
if (isEven(numbers[k])) {
print(byConstant(numbers[k]))
}
}

fn

fn

data

for (k = 0; k < numbers.length; k += 1) {
if (isEven(numbers[k])) {
print(byConstant(numbers[k]))
}
}

fn

fn

data

# Fun 7

## problem: write function that executes `f(g(x))`

mulAndPrint = compose(print, byConstant)
mulAndPrint(numbers[k])

# Fun 7

## my coding process

mulAndPrint = compose(print, byConstant)
mulAndPrint(numbers[k])

## "compose" is a function

mulAndPrint = compose(print, byConstant)
mulAndPrint(numbers[k])
function compose()

## that takes two arguments

mulAndPrint = compose(print, byConstant)
mulAndPrint(numbers[k])
function compose(f, g)

## and returns another function

mulAndPrint = compose(print, byConstant)
mulAndPrint(numbers[k])
function compose(f, g) {
return function() {

}
}

## that expects a single argument

mulAndPrint = compose(print, byConstant)
mulAndPrint(numbers[k])
function compose(f, g) {
return function(x) {

}
}

## and applies original functions to it

mulAndPrint = compose(print, byConstant)
mulAndPrint(numbers[k])
function compose(f, g) {
return function(x) {
return f(g(x))
}
}
mulAndPrint = compose(print, byConstant)
for (k = 0; k < numbers.length; k += 1) {
if (isEven(numbers[k])) {
mulAndPrint(numbers[k])
}
}

fn

data

# Composition

function compose(f, g) {
return function(x) {
return f(g(x))
}
}

# Note: since JavaScript functions return single result, it is easier to compose unary functions

const F = compose(f, g)
F(x)

# Note: composition of pure functions is a pure function

mulAndPrint = compose(print, byConstant)

# pure

print "pollutes" the composed function

# Atomization

initial spaghetti code

mul
print
isEven
...

# Clumping

.bind, compose

const byConstant = mul.bind(null, constant)
const mulAndPrint = compose(print, byConstant)
var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (isEven(numbers[k])) {
mulAndPrint(numbers[k])
}
}

## We still have iteration and side effects mixed with pure functions

var k
for (k = 0; k < list.length; k += 1) {
// call fn(list[k])
}

# Fun 8

## do not use built-in Array methods

var k = 0
for (k = 0; k < numbers.length; k += 1) {
if (isEven(numbers[k])) {
print(byConstant(numbers[k]))
}
}

filter

map

side effect

# map(list, fn)?

function filter(fn, list) {
var k = 0
const result = []
for (k = 0; k < list.length; k += 1) {
if (fn(list[k])) {
result.push(list[k])
}
}
return result
}
// filter(isEven, [1, 2, 3])
// [2]

# filter

callback first

filter(isEven, [1, 2, 3])

# filter

## Callback function is likely to be known right away

evenNumbers = filter.bind(null, isEven)
evenNumbers([1, 2, 3])
// [2]
evenNumbers = filter.bind(null, isEven)
evenNumbers([1, 2, 3])
// [2]

# Declarative style

## We got the filtered numbers "somehow" by providing a predicate

function map(fn, list) {
var k = 0
const result = []
for (k = 0; k < list.length; k += 1) {
result.push(fn(list[k]))
}
return result
}
// map(byConstant, [1, 2, 3])
// [2, 4, 6]

# map

map(byConstant, numbers)

# map

## Callback function is known right away

multiplyAll = map.bind(null, byConstant)
multiplyAll([1, 2, 3])
// [2, 4, 6]
function forEach(fn, list) {
var k = 0
for (k = 0; k < list.length; k += 1) {
fn(list[k])
}
}
// forEach(print, [1, 2, 3])
// 1 2 3

# forEach

## forEach is for "dirty" actions

forEach(print, map(byConstant, filter(isEven, numbers)))

# Partial application FTW

const onlyEven = filter.bind(null, isEven)
forEach(print, map(byConstant, onlyEven(numbers)))
const onlyEven = filter.bind(null, isEven)
const multiply = map.bind(null, byConstant)
forEach(print, multiply(onlyEven(numbers)))
const onlyEven = filter.bind(null, isEven)
const multiply = map.bind(null, byConstant)
const printAll = forEach.bind(null, print)
printAll(multiply(onlyEven(numbers)))

# Fun 9

const onlyEven = filter.bind(null, isEven)
const multiply = map.bind(null, byConstant)
const printAll = forEach.bind(null, print)
printAll(multiply(onlyEven(numbers)))

## problem: write compose for 3 functions using arrow function and collapse the above code

const onlyEven = filter.bind(null, isEven)
const multiply = map.bind(null, byConstant)
const printAll = forEach.bind(null, print)
const compose = (f, g, h) => x => f(g(h(x)))
const solution = compose(printAll, multiply, onlyEven)
solution(numbers)

fn

data

const onlyEven = filter.bind(null, isEven)
const multiply = map.bind(null, byConstant)
const printAll = forEach.bind(null, print)
const compose = (f, g, h) => x => f(g(h(x)))
const solution = compose(printAll, multiply, onlyEven)
solution(numbers)

# Fun 10

## problem: make partial application in {filter, map, forEach} built-in

ugly!

// filter is a binary function
const onlyEven = filter(isEven)
onlyEven([1, 2, 3])
// [2]

## simple: add custom code to each function

function map(fn) {
return function(list) {
var k = 0
const result = []
for (k = 0; k < list.length; k += 1) {
result.push(fn(list[k]))
}
return result
}
}
const multiply = map(byConstant)
multiply([1, 2, 3])
const onlyEven = filter(isEven)
const multiply = map(byConstant)
const printAll = forEach(print)
const compose = (f, g, h) => x => f(g(h(x)))
const solution = compose(printAll, multiply, onlyEven)
solution(numbers)

## I don't like reading the composed function

const onlyEven = filter(isEven)
const multiply = map(byConstant)
const printAll = forEach(print)
const compose = (f, g, h) => x => f(g(h(x)))
const solution = compose(printAll, multiply, onlyEven)
solution(numbers)

# Fun 11

## problem: make it read like the original English description

multiply even numbers by a constant and print the result

const onlyEven = filter(isEven)
const multiply = map(byConstant)
const printAll = forEach(print)
const pipe = (f, g, h) => x => h(g(f(x)))
const solution = pipe(onlyEven, multiply, printAll)
solution(numbers)

## pipe is the reverse of compose

function map(fn, list) { ... }
curry(map)(byConstant)([1, 2, 3])
// [2, 4, 6]

# Fun 12

## problem: write utility function curry that can convert any binary function into two unary functions

function curry(fn) {
return function (x) {
return function (y) {
return fn(x, y)
}
}
}
const curry = fn => x => y => fn(x, y)
const map = curry((fn, list) => {
var k = 0
const result = []
for (k = 0; k < list.length; k += 1){
result.push(fn(list[k]))
}
return result
})
const solution = pipe(
filter(isEven),
map(byConstant),
forEach(print)
)
solution(numbers)

# Curry for shorter code

const solution = pipe(
filter(x => isEven(x)),
map(y => byConstant(y)),
forEach(z => print(z))
)
solution(numbers)

# Where are variables?

Anonymous arrow functions are redundant

# Point-free style

const solution = pipe(
filter(isEven),
map(byConstant),
forEach(print)
)
solution(numbers)

# Hard: keeping track of signatures

const solution = pipe(
filter(isEven),
map(byConstant),
forEach(print)
)
solution(numbers)
// filter :: fn => [x] => [x]
// [x] => [x]
// [x] => [x]
// [x] => undefined
// solution :: [x] => undefined
// numbers is [x]
// undefined

# Fun 13

console.log(['1','2','3'].map(parseFloat))
// 1, 2, 3

## problem: why?

console.log(['1','2','3'].map(parseInt))
// 1, NaN, NaN

# Signatures

// parseFloat :: string => number
console.log(['1','2','3'].map(parseFloat))
// parseInt :: string, radix => number
console.log(['1','2','3'].map(parseInt))
// 1, NaN, NaN
// Array.prototype.map :: cb
// where cb :: item, index, array

# parseInt

// parseInt :: string, radix => number
console.log(['1','2','3'].map(parseInt))
parseInt('1', 0)  // 1
parseInt('2', 1)  // NaN
parseInt('3', 2)  // NaN

# Typical solution

// function parseInt(x, radix)
// but Array.map is (value, index, array)
['1', '2', '3'].map(function (x) {
return parseInt(x)
})

// parseInt :: string, radix => number
unary(parseInt)('2', 1) // 2

## problem: write utility "unary" that forces binary function to ignore second argument

['1','2','3'].map(unary(parseInt))
// [1, 2, 3]

# unary(parseInt)

// parseInt :: string, radix => number
const unary = f => x => f(x)
// unary(parseInt) :: string => number
['1','2','3'].map(unary(parseInt))
// [1, 2, 3]
// parseInt :: string, radix => number
const parse10 = partialRight(parseInt, 10)

# Fun 14 - Adapting parseInt #2

['1','2','3'].map(parse10)
// [1, 2, 3]

# partialRight

const partialRight = (f, b) => a => f(a, b)
// parseInt :: string, radix => number
const parse10 = partialRight(parseInt, 10)
// parse10 :: string => number
['1', '2', '3'].map(parse10)
// 1, 2, 3

# Partial application from the left

function fn(a, b, c) { ... }
var newFn = fn.bind(null, valueA, valueB);
// or
var _ = require('lodash');
var newFn = _.partial(fn, valueA, valueB);
// or
var R = require('ramda');
var newFn = R.partial(fn, valueA, valueB);

# Partial application from the right

const base10 = _.partialRight(parseInt, 10)
['1', '2', '3'].map(base10);
// [1, 2, 3]
// radix is bound,
// index and array arguments are ignored

# Partial application with placeholders

var S = require('spots');
const base10 = S(parseInt, S, 10)
['1', '2', '3'].map(base10);
// [1, 2, 3]

# Partial application by name

// divide by 10
function divide(a, b) { return a / b; }
var selective = require('heroin');
var by10 = selective(divide, { b: 10 });
console.log(by10(10)); // 1 (a = 10, b = 10)
console.log(by10(2)); // 0.2 (a = 2, b = 10)

# Partial application by key

function fn(options) { ... }
var obind = require('obind');
var withBar = obind(fn, { bar: 'bar' });
withBar({ baz: 'baz' });
/*
equivalent to
foo({
bar: 'bar',
baz: 'baz'
})
*/

# Libraries

## Ask questions at gitter.im/ramda/ramda

var numbers = [3, 2, 8]
var constant = 2
// 4
// 16

# Fun 15

const R = require('ramda')
var numbers = [3, 2, 8]
var constant = 2
const solution = R.pipe(
R.filter(isEven),
R.map(R.multiply(constant)),
R.forEach(print)
)
solution(numbers)
const R = require('ramda')
var numbers = [3, 2, 8]
var constant = 2
const solution = R.pipe(
R.filter(isEven),
R.map(R.multiply(constant)),
R.forEach(print)
)
solution(numbers)

## We only needed 2 tiny custom functions

const R = require('ramda')
var numbers = [3, 2, 8]
var constant = 2
const solution = R.pipe(
R.filter(isEven),
R.map(R.multiply(constant)),
R.forEach(print)
)
solution(numbers)

6 functions

2 values

## Methods usually make poor callbacks (because of "this")

forEach(console.log, [1, 2, 3])

Error: Illegal invocation

forEach(console.log.bind(console), [1, 2, 3])

# This workshop

• ### pure React code

const numbers = () => Promise.resolve([3, 2, 8])

# Fun 16 - bonus

hint: look at R.pipeP

const numbers = () => Promise.resolve([3, 2, 8])
const solution = R.pipeP(
numbers,
R.filter(isEven),
R.map(R.multiply(constant)),
R.forEach(print)
)
solution()
// 4
// 16

# Fun 17 - bonus (React in FP)

const Numbers = (numbers) => (
<ul>
{R.map(x => (<li>{x}</li>), numbers)}
</ul>
)
const Container = children => (
<div className="container">
<h1>Numbers are</h1>
{children}
</div>
)
const App = appState => (
Container(Numbers(appState.numbers))
)

list iteration

composition

# App = composition

const App = appState => (
Container(Numbers(appState.numbers))
)
// same as
const App = R.compose(
Container, Numbers, R.prop('numbers')
)

# Read blog post "Getting good at FP"

list of books, tutorials, libraries and people

By Gleb Bahmutov

# Fun* JavaScript Workshop

The principles and basics of functional programming in JavaScript using small coding problems. Pure functions, partial application, composition, iteration, lexical scope, Ramda library.

• 8,684