SlideShare a Scribd company logo
Oh Composable World!
Oh Composable World!
Oh Composable World!
.values()
.flatten()
.sortBy((b) =>
b.CoreRelease.dataValue
.reverse()
.value()
Oh Composable World!
Oh Composable World!
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
const doin_Thangs = str =>
_(str)
.words()
.groupBy(s => s.length)
.orderBy(x => x.length)
.take(2)
.flatten()
.value()
const reactiveUpInHere = el =>
fromEvent(el, 'keyup')
.map(e => e.target.value)
.filter(text => text.length > 2)
.throttle(500)
.distinctUntilChanged()
player
.unitWithinRange(2)
.where(UnitIs.Enemy)
.where(UnitIs.Tank)
.DoDamage(5)
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
Chain Dot Com '
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
‘chain dot com '
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
['chain', 'dot', 'com ']
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
['chain', 'dot', 'com']
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
['com', 'dot', 'chain']
const dotChainy = str => {
const lower = str.toLowerCase()
const words = lower.split(' ')
words.reverse()
for(let i in words) {
words[i] = words[i].trim()
}
let keepers = []
for(let i in words) {
if(words[i].length > 3) {
keepers.push(words[i])
}
}
return keepers.join('')
}
const dotChainy = str => {
const lower = str.toLowerCase()
const words = lower.split(' ')
words.reverse()
for(let i in words) {
words[i] = words[i].trim()
}
let keepers = []
for(let i in words) {
if(words[i].length > 3) {
keepers.push(words[i])
}
}
return keepers.join('')
}
class AppMailer {
constructor() {
this.emailer = new Emailer()
}
removeInvalidAddresses() {
for(let i in this.addresses) {
if(!this.addresses[i].match(/@/)) {
this.addresses.splice(i, 1)
}
}
}
sendEmail({from, to}) {
this.addresses = to
this.emailer.setSender(from)
this.removeInvalidAddresses()
this.emailer.setRecipients(this.addresses)
this.emailer.send()
}
Oh Composable World!
“the major contributor to this complexity in many systems is
the handling of state and the burden that this adds when
trying to analyse and reason about the system.”
Out of the Tar Pit 2006
-Ben Moseley & Peter Marks
Oh Composable World!
Oh Composable World!
const dotChainy = str =>
str
.toLowerCase()
.split(' ')
.map(c => c.trim())
.reverse()
.filter(x => x.length > 3)
.join('')
WHAT IF I TOLD YOU…
Oh Composable World!
WHAT IF I TOLD YOU…
Oh Composable World!
Oh Composable World!
Programming !== Math
try {
return f(x)
} catch(e) {
console.error(e)
}
if(x) {
return f()
} else {
return y
}
for(let thing in things) {
if(thing.amount > 100) keepers.push(thing.name)
}
for (i = 0; i < cars.length; i++) {
text += cars[i] + "<br>";
}
while (i < 10) {
text += "The number is " + i;
i++;
}
let stuff = [1,2,3]
stuff = [1,2]
stuff.splice(0, 2)
stuff.pop()
Assignment
Loops
Callbacks
Side Effects
Branching
Errors
Programming !== Math
Programming != Math
f . g
f . g
dot
f . g = x => f(g(x))
str.toUpperCase().trim()
trim(toUpperCase(str))
Category theory
fn fn
fnfn
Oh Composable World!
Oh Composable World!
Oh Composable World!
Oh Composable World!
a b
f
c
g
a
g
c
f.
a
F(a)
b
f
F(f)
c
g
F(b)
F(g)
F(c)
a
F(a)
g
F(g.f)
c
f
F(c)
.
const contrivedEx1 = str => {
const trimmed = str.trim()
const number = parseInt(trimmed)
const nextNumber = number + 1
return String.fromCharCode(nextNumber)
}
contrivedEx1(' 64 ')
// 'A'
const contrivedEx1 = str =>
[str.trim()]
.map(trimmed => parseInt(trimmed))
.map(number => number + 1)
.map(nextNumber =>
String.fromCharCode(nextNumber))
const contrivedEx1 = str => {
const trimmed = str.trim()
const number = parseInt(trimmed)
const nextNumber = number + 1
return String.fromCharCode(nextNumber)
}
contrivedEx1(' 64 ')
// [‘A’]
const contrivedEx1 = str =>
[str.trim()]
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.map(nextNumber =>
String.fromCharCode(nextNumber))
const contrivedEx1 = str => {
const trimmed = str.trim()
const number = parseInt(trimmed)
const nextNumber = number + 1
return String.fromCharCode(nextNumber)
}
contrivedEx1(' 64 ')
// [‘A’]
const contrivedEx1 = str =>
[str.trim()]
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.map(nextNumber =>
String.fromCharCode(nextNumber))
const contrivedEx1 = str => {
const trimmed = str.trim()
const number = parseInt(trimmed)
const nextNumber = number + 1
return String.fromCharCode(nextNumber)
}
contrivedEx1(' 64 ')
// [‘A’]
const contrivedEx1 = str =>
Box(str.trim())
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.map(nextNumber =>
String.fromCharCode(nextNumber))
contrivedEx1(' 64 ')
// Box(‘A’)
const Box = x =>
({
map: f => Box(f(x))
})
const contrivedEx1 = str =>
Box(str.trim())
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.map(nextNumber =>
String.fromCharCode(nextNumber))
contrivedEx1(' 64 ')
// Box(‘A’)
const Box = x =>
({
map: f => Box(f(x))
})
const contrivedEx1 = str =>
Box(str.trim())
.map(trimmed => new Number(trimmed))
.map(number => number + 1)
.fold(nextNumber =>
String.fromCharCode(nextNumber))
contrivedEx1(' 64 ')
// ‘A’
const Box = x =>
({
map: f => Box(f(x)),
fold: f => f(x)
})
Oh Composable World!
Oh Composable World!
Unified call syntax
Minimized state
Captured Assignment
Forced Control Flow
Assignment
Loops
Callbacks
Side Effects
Branching
Errors
Loops
map
filter
reduce
const range = (i, count) =>
unfold(x => if(x <= count) [x, x+1], i)
range(5,10)
// [ 5, 6, 7, 8, 9, 10 ]
const alphabet = () =>
unfold(x => if(x < 26) [String.fromCharCode(x+65), x+1], 0)
alphabet()
// [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
Assignment
Loops
Callbacks
Side Effects
Branching
Errors
Callbacks
Side Effects
Promise(6).then(six => six / 2)
// Promise(3)
Promise(6).then(six => Promise(six / 2))
// Promise(3)
Promise(6).map(six => six / 2)
// Promise(3)
Promise(6).chain(six => Promise(six / 2))
// Promise(3)
Promise(6).then(six => six / 2)
// Promise(3)
Promise(6).then(six => Promise(six / 2))
// Promise(3)
Promise(6).map(six => six / 2)
// Promise(3)
Promise(6).chain(six => Promise(six / 2))
// Promise(3)
Promise(6).then(six => six / 2)
// Promise(3)
Promise(6).then(six => Promise(six / 2))
// Promise(3)
Promise(6).map(six => six / 2)
// Promise(3)
Promise(6).chain(six => Promise(six / 2))
// Promise(3)
const contrivedEx2 = () =>
fs.readFile('cfg.json', 'utf-8', (err, contents) => {
if(err) throw err
const newContents = contents.replace(/8/g, '6')
fs.writeFile('cfg1.json', newContents, (err, _) => {
if(err) throw err
console.log('success!')
})
})
const readFile = futurize(fs.readFile)
const writeFile = futurize(fs.writeFile)
const contrivedEx2 = () =>
readFile('cfg.json', 'utf-8')
.map(contents => contents.replace(/8/g, '6'))
.chain(replaced => writeFile('cfg1.json', replaced))
const contrivedEx2 = () =>
fs.readFile('cfg.json', 'utf-8', (err, contents) => {
if(err) throw err
const newContents = contents.replace(/8/g, '6')
fs.writeFile('cfg1.json', newContents, (err, _) => {
if(err) throw err
console.log('success!')
})
})
const readFile = futurize(fs.readFile)
const writeFile = futurize(fs.writeFile)
const contrivedEx2 = () =>
readFile('cfg.json', 'utf-8')
.map(contents => contents.replace(/8/g, '6'))
.chain(replaced => writeFile('cfg1.json', replaced))
const readFile = futurize(fs.readFile)
const writeFile = futurize(fs.writeFile)
const contrivedEx2 = () =>
readFile('cfg.json', 'utf-8')
.map(contents => contents.replace(/8/g, '6'))
.chain(replaced => writeFile('cfg1.json', replaced))
contrivedEx2().fork(e => console.error(e),
r => console.log('success!'))
const lib = username =>
getTweets(username)
.map(ts => truncateTo130(ts))
.chain(ts => writeFile('tweets.json', ts))
lib(‘@drboolean’)
const lib = username =>
getTweets(username)
.map(ts => truncateTo130(ts))
.chain(ts => writeFile('tweets.json', ts))
lib(‘@drboolean’)
.chain(f => saveToS3(f))
const lib = username =>
getTweets(username)
.map(ts => truncateTo130(ts))
.chain(ts => writeFile('tweets.json', ts))
lib(‘@drboolean’)
.chain(f => saveToS3(f))
.fork(e => console.error(e),
r => console.log(r))
Oh Composable World!
Assignment
Loops
Callbacks
Side Effects
Branching
Errors
Branching
Errors
Either/Or
Left('no ducks :(').fold(e => `we had an error: ${e}`,
s => s.toUpperCase())
// we had an error: no ducks :(
Right('ducks').fold(e => `we had an error: ${e}`,
s => s.toUpperCase())
//"DUCKS"
Left('no ducks :(').fold(e => `we had an error: ${e}`,
s => s.toUpperCase())
// we had an error: no ducks :(
Right('ducks').fold(e => `we had an error: ${e}`,
s => s.toUpperCase())
//"DUCKS"
Left('no ducks :(').fold(e => `we had an error: ${e}`,
s => s.toUpperCase())
// we had an error: no ducks :(
Right('ducks').fold(e => `we had an error: ${e}`,
s => s.toUpperCase())
//"DUCKS"
leftOrRight.fold(e => `we had an error: ${e}`,
s => s.toUpperCase())
Right({hair: 'brown'})
.map(obj => obj.hair)
.map(brown => brown.length)
.chain(five => Right(five * 2))
// Right(10)
Left('ignored')
.map(obj => obj.hair)
.map(brown => brown.length)
.chain(five => Left(five * 2))
// Left('ignored')
const getConfig = () => {
try {
return fs.readFileSync('cfg.json')
} catch(e) {
return null
}
}
const contrivedEx3 = () => {
const cfg = getConfig()
if(cfg) {
const parsed = JSON.parse(cfg)
return parsed.port
} else {
return 3000
}
}
const getConfig = () =>
Either.try(fs.readFileSync)('cfg.json')
const contrivedEx3 = () =>
getConfig()
.map(JSON.parse)
.fold(e => 3000, c => c.port)
const getConfig = () =>
Either.try(fs.readFileSync)('cfg.json')
const contrivedEx3 = () =>
getConfig()
.map(JSON.parse)
.fold(e => 3000, c => c.port)
const getConfig = () => {
try {
return fs.readFileSync('cfg.json')
} catch(e) {
return null
}
}
const contrivedEx3 = () => {
const cfg = getConfig()
if(cfg) {
const parsed = JSON.parse(cfg)
return parsed.port
} else {
return 3000
}
}
Claim
const contrivedEx4 = user => {
const address = user.address
if(address) {
const zip = address.match(/(d{5})$/i)
if(zip) {
const city = cityByZip(zip)
if(city) {
return city
} else {
return "can't find city"
}
}
}
return "can't find city"
}
const contrivedEx4 = user =>
fromNullable(user.address)
.chain(a => fromNullable(a.match(/(d{5})$/i)))
.chain(zip => fromNullable(cityByZip(zip)))
.fold(() => "can't find city", city => city)
const contrivedEx4 = user => {
const address = user.address
if(address) {
const zip = address.match(/(d{5})$/i)
if(zip) {
const city = cityByZip(zip)
if(city) {
return city
} else {
return "can't find city"
}
}
}
return "can't find city"
}
const contrivedEx4 = user =>
fromNullable(user.address)
.chain(a => fromNullable(a.match(/(d{5})$/i)))
.chain(zip => fromNullable(cityByZip(zip)))
.fold(() => "can't find city", city => city)
Assignment
Loops
Callbacks
Side Effects
Branching
Errors
const depObjs = b =>
List(b.deps).flatMap(next =>
findDependencyByProject(next.Project.name, b.previous.deps)
.fold(x => x,
found => makeArgs(next, found)))
const mapBuildsAndDepsForDiffQueue = (builds) =>
List(builds)
.filter(b => b.previous)
.flatMap(b => makeArgs(b, b.previous).concat(depObjs(b)))
.filter(b => b)
.toJS()
const filterExistingDiffs = (items) =>
List(items).traverse(Task.of, (i) =>
find(Diff, { BuildId: i.buildId, DiffId: i.prevId, type: i.method })
.map(e => e.swap().getOrElse(null))
.map(bs => bs.filter(x => x).toJS())
const buildProject = ({branch, sha}) =>
queueUnzipWwwOnS3(sha)
.chain(() => isReleaseOrMainBranch(branch))
.fold(() => _.noop,
() =>
generateReport(sha)
.chain(queueDiffsForTileBuildsAndDeps)
.chain(() =>
getHeadCommit(sha)
.fold(() => Task.of(null),
head =>
makeVrtDeployment(head, sha)
.chain(() => createPrApp(head, sha))))
.fork(console.error,
console.log))
Oh Composable World!
Oh Composable World!
const vrtReport = ({sha, email, platforms}) =>
rejectFinishedPlatformOptions(platforms)
.chain(plats => plats.map(gatherScreenshots))
.chain(shots =>
fromNullable(sha)
.fold(() => findLastRef(),
() => findBuild({sha}))
.chain(ref =>
renderReport(shots, ref, email)))
.fork(e => e, r => r)
Harder to hack
const getConfig = () =>
Either.try(fs.readFileSync)('cfg.json')
const contrivedEx3 = () =>
getConfig()
.map(JSON.parse)
.fold(e => 3000, c => c.port)
Safer
Oh Composable World!
const ProfileLink = user =>
<a href={`/users/${u.id}`}>{u.name}</a>
const Header = str =>
<h1>Now Viewing {str}</h1>
Component :: a -> JSX
a JSX
f
a JSX
f
b
g
a JSX
f
b
g
a JSX
f
b
g
const Comp = g =>
({
fold: g,
contramap: f =>
Comp(x => g(f(x)))
})
const Comp = g =>
({
fold: g,
contramap: f =>
Comp(x => g(f(x)))
})
const Heading = str =>
<h1>Now Viewing {str}</h1>
const Title = Comp(Heading).contramap(s => s.pageName)
const Title = Comp(Heading).contramap(s => s.pageName)
Title.fold({ pageName: ‘Home',
currentUser: { id: 2, name: 'Chris Harrison’ } })
// <h1>Now Viewing Home</h1>
const Comp = g =>
({
fold: g,
contramap: f =>
Comp(x => g(f(x)))
})
const Heading = str =>
<h1>Now Viewing {str}</h1>
const Comp = g =>
({
fold: g,
contramap: f =>
Comp(x => g(f(x)))
})
const Comp = g =>
({
fold: g,
contramap: f =>
Comp(x => g(f(x))),
concat: other =>
Comp(x => <div>{g(x)} {other.fold(x)}</div>)
})
const ProfileLink = user =>
<a href={`/users/${u.id}`}>{u.name}</a>)
const Heading = str =>
<h1>Now Viewing {str}</h1>
const Heading = Comp(Title).contramap(s => s.pageName)
const Link = Comp(ProfileLink).contramap(s => s.currentUser)
const App = Heading.concat(Link)
const ProfileLink = user =>
<a href={`/users/${u.id}`}>{u.name}</a>)
const Heading = str =>
<h1>Now Viewing {str}</h1>
const Heading = Comp(Title).contramap(s => s.pageName)
const Link = Comp(ProfileLink).contramap(s => s.currentUser)
const App = Heading.concat(Link)
App.fold({ pageName: ‘Home',
currentUser: { name: 'Chris Harrison’ } })
// <div>
// <h1>Now Viewing Home</h1>
// <a href="/users/22">Chris Harrison</a>
// </div>
Reducer :: (a, b) -> a
const Reducer = g =>
({
fold: g,
contramap: f =>
Reducer((acc, x) => g(acc, f(x))),
map: f =>
Reducer((acc, x) => f(g(acc, x)))
})
const r = Reducer((acc, x) => acc.concat(x))
.contramap(x => `The number is ${x}`)
.map(x => x + '! ')
[1,2,3].reduce(r.fold, '')
// The number is 1! The number is 2! The number is 3!
const Reducer = g =>
({
fold: g,
contramap: f =>
Reducer((acc, x) => g(acc, f(x))),
map: f =>
Reducer((acc, x) => f(g(acc, x)))
})
const Reducer = g =>
({
fold: g,
contramap: f =>
Reducer((acc, x) => g(acc, f(x))),
map: f =>
Reducer((acc, x) => f(g(acc, x)))
})
const Reducer = g =>
({
fold: g,
contramap: f =>
Reducer((acc, x) => g(acc, f(x))),
map: f =>
Reducer((acc, x) => f(g(acc, x))),
concat: o =>
Reducer((acc, x) => o.fold(g(acc, x), x))
})
const appReducer = Reducer((state, action) => {
switch (action.type) {
case 'set_visibility_filter':
return Object.assign({}, state, {
visibilityFilter: action.filter
})
default:
return state
}
})
const todoReducer = Reducer((state, action) => {
switch (action.type) {
case 'new_todo':
const t = { id: 0, title: action.payload.title }
return Object.assign({}, state, {
todos: state.todos.concat(t)
})
default:
return state
}
})
const todoApp =
appReducer
.concat(todoReducer)
.contramap(action => Object.assign({filter: 'all'}, action))
.map(s => Object.assign({}, s, {lastUpdated: Date()}))
const todoApp =
appReducer
.concat(todoReducer)
.contramap(action => Object.assign({filter: 'all'}, action))
.map(s => Object.assign({}, s, {lastUpdated: Date()}))
todoApp.fold({visibilityFilter: ‘complete'},
{type: ‘set_visibility_filter'})
// { visibilityFilter: 'all',
// lastUpdated: 'Sun Aug 21 2016 11:04:48 GMT-0700 (PDT)' }
const todoApp =
appReducer
.contramap(action => Object.assign({filter: 'all'}, action))
.concat(todoReducer)
.map(s => Object.assign({}, s, {lastUpdated: Date()}))
todoApp.fold({visibilityFilter: ‘complete'},
{type: ‘set_visibility_filter'})
// { visibilityFilter: 'all',
// lastUpdated: 'Sun Aug 21 2016 11:04:48 GMT-0700 (PDT)' }
Hoc :: Component -> Component
const Hoc = g =>
({
fold: g,
concat: other =>
Hoc(x => g(other.fold(x)))
})
const hoc = Hoc(withReducer(‘state', 'dispatch', todoApp.fold, {todos: []}))
const Todos = hoc.fold(({ state, dispatch }) =>
<div>
<span>Filter: {state.visibilityFilter}</span>
<ul>
{ state.todos.map(t => <li>{t.title}</li>) }
</ul>
<button onClick={() =>
dispatch({ type: 'new_todo', payload: {title: 'New todo'}})}>
Add Todo
</button>
<button onClick={() =>
dispatch({ type: 'set_visibility_filter' })}>
Set Visibility
</button>
</div>
)
const App = Heading.contramap(s => s.pageName)
.concat(TodoComp)
.concat(Link.contramap(s => s.currentUser))
.fold({ pageName: 'Home',
currentUser: {id: 2, name: 'Boris' } })
ReactDOM.render(App, document.getElementById('body'))
const TodoComp = Component(classToFn(Todos))
const Heading = Component(s => <h1>Now Viewing {s}</h1>)
const Link = Component(u => <a href={`/users/${u.id}`}>{u.name}</a>)
https://jsfiddle.net/cnsn8yk2/9/
map =
compose =
program construction
// Functor
Box.of(20).map(x => x / 2)
// Box(10)
// Monad
Box.of(true).chain(x => Box.of(!x))
// Box(false)
// Monoid
Box.of('small').concat(Box.of('pox'))
// Box('smallpox')
// Applicative
Box.of(x => x + 1).ap(2)
// Box(3)
// Traversable
Box.of(3).traverse(Either.of, x => fromNullable(x))
// Right(Box(3))
// Natural transformation
eitherToBox(fromNullable(null))
// Box(null)
Oh Composable World!
Oh Composable World!
Professor Frisby’s Composable JavaScript
@drboolean
@drboolean

More Related Content

What's hot

Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
Baruch Sadogursky
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
Loïc Knuchel
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..
Dr. Volkan OBAN
 
하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4
Kwang Yul Seo
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
riue
 
Scala Parallel Collections
Scala Parallel CollectionsScala Parallel Collections
Scala Parallel Collections
Aleksandar Prokopec
 
Advanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIAdvanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part II
Dr. Volkan OBAN
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
Eleanor McHugh
 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
Stephan Janssen
 
Kotlin class
Kotlin classKotlin class
Kotlin class
Myeongin Woo
 
Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...
Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...
Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...
Dr. Volkan OBAN
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
PROIDEA
 
Functional programming in scala
Functional programming in scalaFunctional programming in scala
Functional programming in scala
Siarhiej Siemianchuk
 
The secrets of inverse brogramming
The secrets of inverse brogrammingThe secrets of inverse brogramming
The secrets of inverse brogramming
Richie Cotton
 
Useful javascript
Useful javascriptUseful javascript
Useful javascript
Lei Kang
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
Baruch Sadogursky
 
Programming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYProgramming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAY
vikram mahendra
 
Groovy collection api
Groovy collection apiGroovy collection api
Groovy collection api
trygvea
 

What's hot (18)

Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014Groovy puzzlers по русски с Joker 2014
Groovy puzzlers по русски с Joker 2014
 
Programmation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScriptProgrammation fonctionnelle en JavaScript
Programmation fonctionnelle en JavaScript
 
imager package in R and examples..
imager package in R and examples..imager package in R and examples..
imager package in R and examples..
 
하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4하스켈 프로그래밍 입문 4
하스켈 프로그래밍 입문 4
 
関数潮流(Function Tendency)
関数潮流(Function Tendency)関数潮流(Function Tendency)
関数潮流(Function Tendency)
 
Scala Parallel Collections
Scala Parallel CollectionsScala Parallel Collections
Scala Parallel Collections
 
Advanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part IIAdvanced Data Visualization Examples with R-Part II
Advanced Data Visualization Examples with R-Part II
 
Implementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 reduxImplementing virtual machines in go & c 2018 redux
Implementing virtual machines in go & c 2018 redux
 
Scala by Luc Duponcheel
Scala by Luc DuponcheelScala by Luc Duponcheel
Scala by Luc Duponcheel
 
Kotlin class
Kotlin classKotlin class
Kotlin class
 
Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...
Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...
Some R Examples[R table and Graphics] -Advanced Data Visualization in R (Some...
 
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
JDD2015: Functional programing and Event Sourcing - a pair made in heaven - e...
 
Functional programming in scala
Functional programming in scalaFunctional programming in scala
Functional programming in scala
 
The secrets of inverse brogramming
The secrets of inverse brogrammingThe secrets of inverse brogramming
The secrets of inverse brogramming
 
Useful javascript
Useful javascriptUseful javascript
Useful javascript
 
The Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 SeasonsThe Groovy Puzzlers – The Complete 01 and 02 Seasons
The Groovy Puzzlers – The Complete 01 and 02 Seasons
 
Programming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAYProgramming in lua STRING AND ARRAY
Programming in lua STRING AND ARRAY
 
Groovy collection api
Groovy collection apiGroovy collection api
Groovy collection api
 

Viewers also liked

Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
Brian Lonsdorf
 
Functional Reactive Programming in Javascript
Functional Reactive Programming in JavascriptFunctional Reactive Programming in Javascript
Functional Reactive Programming in Javascript
Brian Lonsdorf
 
Functional js class
Functional js classFunctional js class
Functional js class
Brian Lonsdorf
 
Liftin every day
Liftin every dayLiftin every day
Liftin every day
Brian Lonsdorf
 
Js for learning
Js for learningJs for learning
Js for learning
Brian Lonsdorf
 
Underscore
UnderscoreUnderscore
Underscore
Brian Lonsdorf
 

Viewers also liked (6)

Fact, Fiction, and FP
Fact, Fiction, and FPFact, Fiction, and FP
Fact, Fiction, and FP
 
Functional Reactive Programming in Javascript
Functional Reactive Programming in JavascriptFunctional Reactive Programming in Javascript
Functional Reactive Programming in Javascript
 
Functional js class
Functional js classFunctional js class
Functional js class
 
Liftin every day
Liftin every dayLiftin every day
Liftin every day
 
Js for learning
Js for learningJs for learning
Js for learning
 
Underscore
UnderscoreUnderscore
Underscore
 

Similar to Oh Composable World!

Node.js in 2020 - part 3
Node.js in 2020 - part 3Node.js in 2020 - part 3
Node.js in 2020 - part 3
Timur Shemsedinov
 
Patterns and antipatterns
Patterns and antipatternsPatterns and antipatterns
Patterns and antipatterns
Timur Shemsedinov
 
Super Advanced Python –act1
Super Advanced Python –act1Super Advanced Python –act1
Super Advanced Python –act1
Ke Wei Louis
 
How are Race Conditions in single threaded JavaScript possible?
How are Race Conditions in single threaded JavaScript possible?How are Race Conditions in single threaded JavaScript possible?
How are Race Conditions in single threaded JavaScript possible?
Timur Shemsedinov
 
Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語
ikdysfm
 
Prototype programming in JavaScript
Prototype programming in JavaScriptPrototype programming in JavaScript
Prototype programming in JavaScript
Timur Shemsedinov
 
Programming Languages: comparison, history, future
Programming Languages: comparison, history, futureProgramming Languages: comparison, history, future
Programming Languages: comparison, history, future
Timur Shemsedinov
 
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
Timur Shemsedinov
 
CLUSTERGRAM
CLUSTERGRAMCLUSTERGRAM
CLUSTERGRAM
Dr. Volkan OBAN
 
Everything is composable
Everything is composableEverything is composable
Everything is composable
Victor Igor
 
Node.js in 2020 - part 2
Node.js in 2020 - part 2Node.js in 2020 - part 2
Node.js in 2020 - part 2
Timur Shemsedinov
 
Monadologie
MonadologieMonadologie
Monadologie
league
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and Go
Eleanor McHugh
 
Asynchronous programming and mutlithreading
Asynchronous programming and mutlithreadingAsynchronous programming and mutlithreading
Asynchronous programming and mutlithreading
Timur Shemsedinov
 
Lập trình Python cơ bản
Lập trình Python cơ bảnLập trình Python cơ bản
Lập trình Python cơ bản
Nguyen Thi Lan Phuong
 
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
Revolution Analytics
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For Google
Eleanor McHugh
 
Introduction to matlab lecture 3 of 4
Introduction to matlab lecture 3 of 4Introduction to matlab lecture 3 of 4
Introduction to matlab lecture 3 of 4
Randa Elanwar
 
The Magnificent Seven
The Magnificent SevenThe Magnificent Seven
The Magnificent Seven
Mike Fogus
 
Py3k
Py3kPy3k

Similar to Oh Composable World! (20)

Node.js in 2020 - part 3
Node.js in 2020 - part 3Node.js in 2020 - part 3
Node.js in 2020 - part 3
 
Patterns and antipatterns
Patterns and antipatternsPatterns and antipatterns
Patterns and antipatterns
 
Super Advanced Python –act1
Super Advanced Python –act1Super Advanced Python –act1
Super Advanced Python –act1
 
How are Race Conditions in single threaded JavaScript possible?
How are Race Conditions in single threaded JavaScript possible?How are Race Conditions in single threaded JavaScript possible?
How are Race Conditions in single threaded JavaScript possible?
 
Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語Haskellで学ぶ関数型言語
Haskellで学ぶ関数型言語
 
Prototype programming in JavaScript
Prototype programming in JavaScriptPrototype programming in JavaScript
Prototype programming in JavaScript
 
Programming Languages: comparison, history, future
Programming Languages: comparison, history, futureProgramming Languages: comparison, history, future
Programming Languages: comparison, history, future
 
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
Новое в JavaScript: ES.Next, ECMAScript 2020, ES11, ES10, ES9, ES8, ES7, ES6,...
 
CLUSTERGRAM
CLUSTERGRAMCLUSTERGRAM
CLUSTERGRAM
 
Everything is composable
Everything is composableEverything is composable
Everything is composable
 
Node.js in 2020 - part 2
Node.js in 2020 - part 2Node.js in 2020 - part 2
Node.js in 2020 - part 2
 
Monadologie
MonadologieMonadologie
Monadologie
 
Implementing Software Machines in C and Go
Implementing Software Machines in C and GoImplementing Software Machines in C and Go
Implementing Software Machines in C and Go
 
Asynchronous programming and mutlithreading
Asynchronous programming and mutlithreadingAsynchronous programming and mutlithreading
Asynchronous programming and mutlithreading
 
Lập trình Python cơ bản
Lập trình Python cơ bảnLập trình Python cơ bản
Lập trình Python cơ bản
 
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
 
Go: It's Not Just For Google
Go: It's Not Just For GoogleGo: It's Not Just For Google
Go: It's Not Just For Google
 
Introduction to matlab lecture 3 of 4
Introduction to matlab lecture 3 of 4Introduction to matlab lecture 3 of 4
Introduction to matlab lecture 3 of 4
 
The Magnificent Seven
The Magnificent SevenThe Magnificent Seven
The Magnificent Seven
 
Py3k
Py3kPy3k
Py3k
 

Recently uploaded

How to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptxHow to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptx
Adam Dunkels
 
find out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challengesfind out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challenges
huseindihon
 
Pigging Solutions Sustainability brochure.pdf
Pigging Solutions Sustainability brochure.pdfPigging Solutions Sustainability brochure.pdf
Pigging Solutions Sustainability brochure.pdf
Pigging Solutions
 
Details of description part II: Describing images in practice - Tech Forum 2024
Details of description part II: Describing images in practice - Tech Forum 2024Details of description part II: Describing images in practice - Tech Forum 2024
Details of description part II: Describing images in practice - Tech Forum 2024
BookNet Canada
 
How RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptxHow RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptx
SynapseIndia
 
7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf
Enterprise Wired
 
RPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptx
RPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptxRPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptx
RPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptx
SynapseIndia
 
Comparison Table of DiskWarrior Alternatives.pdf
Comparison Table of DiskWarrior Alternatives.pdfComparison Table of DiskWarrior Alternatives.pdf
Comparison Table of DiskWarrior Alternatives.pdf
Andrey Yasko
 
20240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 202420240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 2024
Matthew Sinclair
 
WPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide DeckWPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide Deck
Lidia A.
 
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdfINDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
jackson110191
 
Password Rotation in 2024 is still Relevant
Password Rotation in 2024 is still RelevantPassword Rotation in 2024 is still Relevant
Password Rotation in 2024 is still Relevant
Bert Blevins
 
Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
Tatiana Al-Chueyr
 
What's New in Copilot for Microsoft365 May 2024.pptx
What's New in Copilot for Microsoft365 May 2024.pptxWhat's New in Copilot for Microsoft365 May 2024.pptx
What's New in Copilot for Microsoft365 May 2024.pptx
Stephanie Beckett
 
Mitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing SystemsMitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing Systems
ScyllaDB
 
20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf
Sally Laouacheria
 
DealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 editionDealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 edition
Yevgen Sysoyev
 
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Bert Blevins
 
Coordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar SlidesCoordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar Slides
Safe Software
 
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Erasmo Purificato
 

Recently uploaded (20)

How to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptxHow to Build a Profitable IoT Product.pptx
How to Build a Profitable IoT Product.pptx
 
find out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challengesfind out more about the role of autonomous vehicles in facing global challenges
find out more about the role of autonomous vehicles in facing global challenges
 
Pigging Solutions Sustainability brochure.pdf
Pigging Solutions Sustainability brochure.pdfPigging Solutions Sustainability brochure.pdf
Pigging Solutions Sustainability brochure.pdf
 
Details of description part II: Describing images in practice - Tech Forum 2024
Details of description part II: Describing images in practice - Tech Forum 2024Details of description part II: Describing images in practice - Tech Forum 2024
Details of description part II: Describing images in practice - Tech Forum 2024
 
How RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptxHow RPA Help in the Transportation and Logistics Industry.pptx
How RPA Help in the Transportation and Logistics Industry.pptx
 
7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf7 Most Powerful Solar Storms in the History of Earth.pdf
7 Most Powerful Solar Storms in the History of Earth.pdf
 
RPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptx
RPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptxRPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptx
RPA In Healthcare Benefits, Use Case, Trend And Challenges 2024.pptx
 
Comparison Table of DiskWarrior Alternatives.pdf
Comparison Table of DiskWarrior Alternatives.pdfComparison Table of DiskWarrior Alternatives.pdf
Comparison Table of DiskWarrior Alternatives.pdf
 
20240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 202420240704 QFM023 Engineering Leadership Reading List June 2024
20240704 QFM023 Engineering Leadership Reading List June 2024
 
WPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide DeckWPRiders Company Presentation Slide Deck
WPRiders Company Presentation Slide Deck
 
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdfINDIAN AIR FORCE FIGHTER PLANES LIST.pdf
INDIAN AIR FORCE FIGHTER PLANES LIST.pdf
 
Password Rotation in 2024 is still Relevant
Password Rotation in 2024 is still RelevantPassword Rotation in 2024 is still Relevant
Password Rotation in 2024 is still Relevant
 
Best Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdfBest Practices for Effectively Running dbt in Airflow.pdf
Best Practices for Effectively Running dbt in Airflow.pdf
 
What's New in Copilot for Microsoft365 May 2024.pptx
What's New in Copilot for Microsoft365 May 2024.pptxWhat's New in Copilot for Microsoft365 May 2024.pptx
What's New in Copilot for Microsoft365 May 2024.pptx
 
Mitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing SystemsMitigating the Impact of State Management in Cloud Stream Processing Systems
Mitigating the Impact of State Management in Cloud Stream Processing Systems
 
20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf20240702 Présentation Plateforme GenAI.pdf
20240702 Présentation Plateforme GenAI.pdf
 
DealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 editionDealBook of Ukraine: 2024 edition
DealBook of Ukraine: 2024 edition
 
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
Understanding Insider Security Threats: Types, Examples, Effects, and Mitigat...
 
Coordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar SlidesCoordinate Systems in FME 101 - Webinar Slides
Coordinate Systems in FME 101 - Webinar Slides
 
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
Paradigm Shifts in User Modeling: A Journey from Historical Foundations to Em...
 

Oh Composable World!

  • 7. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
  • 8. const doin_Thangs = str => _(str) .words() .groupBy(s => s.length) .orderBy(x => x.length) .take(2) .flatten() .value()
  • 9. const reactiveUpInHere = el => fromEvent(el, 'keyup') .map(e => e.target.value) .filter(text => text.length > 2) .throttle(500) .distinctUntilChanged()
  • 11. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
  • 12. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
  • 13. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('') Chain Dot Com '
  • 14. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('') ‘chain dot com '
  • 15. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('') ['chain', 'dot', 'com ']
  • 16. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('') ['chain', 'dot', 'com']
  • 17. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('') ['com', 'dot', 'chain']
  • 18. const dotChainy = str => { const lower = str.toLowerCase() const words = lower.split(' ') words.reverse() for(let i in words) { words[i] = words[i].trim() } let keepers = [] for(let i in words) { if(words[i].length > 3) { keepers.push(words[i]) } } return keepers.join('') }
  • 19. const dotChainy = str => { const lower = str.toLowerCase() const words = lower.split(' ') words.reverse() for(let i in words) { words[i] = words[i].trim() } let keepers = [] for(let i in words) { if(words[i].length > 3) { keepers.push(words[i]) } } return keepers.join('') }
  • 20. class AppMailer { constructor() { this.emailer = new Emailer() } removeInvalidAddresses() { for(let i in this.addresses) { if(!this.addresses[i].match(/@/)) { this.addresses.splice(i, 1) } } } sendEmail({from, to}) { this.addresses = to this.emailer.setSender(from) this.removeInvalidAddresses() this.emailer.setRecipients(this.addresses) this.emailer.send() }
  • 22. “the major contributor to this complexity in many systems is the handling of state and the burden that this adds when trying to analyse and reason about the system.” Out of the Tar Pit 2006 -Ben Moseley & Peter Marks
  • 25. const dotChainy = str => str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
  • 26. WHAT IF I TOLD YOU…
  • 28. WHAT IF I TOLD YOU…
  • 32. try { return f(x) } catch(e) { console.error(e) }
  • 33. if(x) { return f() } else { return y }
  • 34. for(let thing in things) { if(thing.amount > 100) keepers.push(thing.name) } for (i = 0; i < cars.length; i++) { text += cars[i] + "<br>"; } while (i < 10) { text += "The number is " + i; i++; }
  • 35. let stuff = [1,2,3] stuff = [1,2]
  • 40. f . g
  • 42. f . g = x => f(g(x))
  • 45. fn fn
  • 46. fnfn
  • 55. const contrivedEx1 = str => { const trimmed = str.trim() const number = parseInt(trimmed) const nextNumber = number + 1 return String.fromCharCode(nextNumber) } contrivedEx1(' 64 ') // 'A'
  • 56. const contrivedEx1 = str => [str.trim()] .map(trimmed => parseInt(trimmed)) .map(number => number + 1) .map(nextNumber => String.fromCharCode(nextNumber)) const contrivedEx1 = str => { const trimmed = str.trim() const number = parseInt(trimmed) const nextNumber = number + 1 return String.fromCharCode(nextNumber) } contrivedEx1(' 64 ') // [‘A’]
  • 57. const contrivedEx1 = str => [str.trim()] .map(trimmed => new Number(trimmed)) .map(number => number + 1) .map(nextNumber => String.fromCharCode(nextNumber)) const contrivedEx1 = str => { const trimmed = str.trim() const number = parseInt(trimmed) const nextNumber = number + 1 return String.fromCharCode(nextNumber) } contrivedEx1(' 64 ') // [‘A’]
  • 58. const contrivedEx1 = str => [str.trim()] .map(trimmed => new Number(trimmed)) .map(number => number + 1) .map(nextNumber => String.fromCharCode(nextNumber)) const contrivedEx1 = str => { const trimmed = str.trim() const number = parseInt(trimmed) const nextNumber = number + 1 return String.fromCharCode(nextNumber) } contrivedEx1(' 64 ') // [‘A’]
  • 59. const contrivedEx1 = str => Box(str.trim()) .map(trimmed => new Number(trimmed)) .map(number => number + 1) .map(nextNumber => String.fromCharCode(nextNumber)) contrivedEx1(' 64 ') // Box(‘A’) const Box = x => ({ map: f => Box(f(x)) })
  • 60. const contrivedEx1 = str => Box(str.trim()) .map(trimmed => new Number(trimmed)) .map(number => number + 1) .map(nextNumber => String.fromCharCode(nextNumber)) contrivedEx1(' 64 ') // Box(‘A’) const Box = x => ({ map: f => Box(f(x)) })
  • 61. const contrivedEx1 = str => Box(str.trim()) .map(trimmed => new Number(trimmed)) .map(number => number + 1) .fold(nextNumber => String.fromCharCode(nextNumber)) contrivedEx1(' 64 ') // ‘A’ const Box = x => ({ map: f => Box(f(x)), fold: f => f(x) })
  • 64. Unified call syntax Minimized state Captured Assignment Forced Control Flow
  • 66. Loops
  • 68. const range = (i, count) => unfold(x => if(x <= count) [x, x+1], i) range(5,10) // [ 5, 6, 7, 8, 9, 10 ]
  • 69. const alphabet = () => unfold(x => if(x < 26) [String.fromCharCode(x+65), x+1], 0) alphabet() // [A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z]
  • 72. Promise(6).then(six => six / 2) // Promise(3) Promise(6).then(six => Promise(six / 2)) // Promise(3) Promise(6).map(six => six / 2) // Promise(3) Promise(6).chain(six => Promise(six / 2)) // Promise(3)
  • 73. Promise(6).then(six => six / 2) // Promise(3) Promise(6).then(six => Promise(six / 2)) // Promise(3) Promise(6).map(six => six / 2) // Promise(3) Promise(6).chain(six => Promise(six / 2)) // Promise(3)
  • 74. Promise(6).then(six => six / 2) // Promise(3) Promise(6).then(six => Promise(six / 2)) // Promise(3) Promise(6).map(six => six / 2) // Promise(3) Promise(6).chain(six => Promise(six / 2)) // Promise(3)
  • 75. const contrivedEx2 = () => fs.readFile('cfg.json', 'utf-8', (err, contents) => { if(err) throw err const newContents = contents.replace(/8/g, '6') fs.writeFile('cfg1.json', newContents, (err, _) => { if(err) throw err console.log('success!') }) })
  • 76. const readFile = futurize(fs.readFile) const writeFile = futurize(fs.writeFile) const contrivedEx2 = () => readFile('cfg.json', 'utf-8') .map(contents => contents.replace(/8/g, '6')) .chain(replaced => writeFile('cfg1.json', replaced))
  • 77. const contrivedEx2 = () => fs.readFile('cfg.json', 'utf-8', (err, contents) => { if(err) throw err const newContents = contents.replace(/8/g, '6') fs.writeFile('cfg1.json', newContents, (err, _) => { if(err) throw err console.log('success!') }) }) const readFile = futurize(fs.readFile) const writeFile = futurize(fs.writeFile) const contrivedEx2 = () => readFile('cfg.json', 'utf-8') .map(contents => contents.replace(/8/g, '6')) .chain(replaced => writeFile('cfg1.json', replaced))
  • 78. const readFile = futurize(fs.readFile) const writeFile = futurize(fs.writeFile) const contrivedEx2 = () => readFile('cfg.json', 'utf-8') .map(contents => contents.replace(/8/g, '6')) .chain(replaced => writeFile('cfg1.json', replaced)) contrivedEx2().fork(e => console.error(e), r => console.log('success!'))
  • 79. const lib = username => getTweets(username) .map(ts => truncateTo130(ts)) .chain(ts => writeFile('tweets.json', ts)) lib(‘@drboolean’)
  • 80. const lib = username => getTweets(username) .map(ts => truncateTo130(ts)) .chain(ts => writeFile('tweets.json', ts)) lib(‘@drboolean’) .chain(f => saveToS3(f))
  • 81. const lib = username => getTweets(username) .map(ts => truncateTo130(ts)) .chain(ts => writeFile('tweets.json', ts)) lib(‘@drboolean’) .chain(f => saveToS3(f)) .fork(e => console.error(e), r => console.log(r))
  • 86. Left('no ducks :(').fold(e => `we had an error: ${e}`, s => s.toUpperCase()) // we had an error: no ducks :( Right('ducks').fold(e => `we had an error: ${e}`, s => s.toUpperCase()) //"DUCKS"
  • 87. Left('no ducks :(').fold(e => `we had an error: ${e}`, s => s.toUpperCase()) // we had an error: no ducks :( Right('ducks').fold(e => `we had an error: ${e}`, s => s.toUpperCase()) //"DUCKS"
  • 88. Left('no ducks :(').fold(e => `we had an error: ${e}`, s => s.toUpperCase()) // we had an error: no ducks :( Right('ducks').fold(e => `we had an error: ${e}`, s => s.toUpperCase()) //"DUCKS"
  • 89. leftOrRight.fold(e => `we had an error: ${e}`, s => s.toUpperCase())
  • 90. Right({hair: 'brown'}) .map(obj => obj.hair) .map(brown => brown.length) .chain(five => Right(five * 2)) // Right(10)
  • 91. Left('ignored') .map(obj => obj.hair) .map(brown => brown.length) .chain(five => Left(five * 2)) // Left('ignored')
  • 92. const getConfig = () => { try { return fs.readFileSync('cfg.json') } catch(e) { return null } } const contrivedEx3 = () => { const cfg = getConfig() if(cfg) { const parsed = JSON.parse(cfg) return parsed.port } else { return 3000 } }
  • 93. const getConfig = () => Either.try(fs.readFileSync)('cfg.json') const contrivedEx3 = () => getConfig() .map(JSON.parse) .fold(e => 3000, c => c.port)
  • 94. const getConfig = () => Either.try(fs.readFileSync)('cfg.json') const contrivedEx3 = () => getConfig() .map(JSON.parse) .fold(e => 3000, c => c.port) const getConfig = () => { try { return fs.readFileSync('cfg.json') } catch(e) { return null } } const contrivedEx3 = () => { const cfg = getConfig() if(cfg) { const parsed = JSON.parse(cfg) return parsed.port } else { return 3000 } }
  • 95. Claim
  • 96. const contrivedEx4 = user => { const address = user.address if(address) { const zip = address.match(/(d{5})$/i) if(zip) { const city = cityByZip(zip) if(city) { return city } else { return "can't find city" } } } return "can't find city" }
  • 97. const contrivedEx4 = user => fromNullable(user.address) .chain(a => fromNullable(a.match(/(d{5})$/i))) .chain(zip => fromNullable(cityByZip(zip))) .fold(() => "can't find city", city => city)
  • 98. const contrivedEx4 = user => { const address = user.address if(address) { const zip = address.match(/(d{5})$/i) if(zip) { const city = cityByZip(zip) if(city) { return city } else { return "can't find city" } } } return "can't find city" } const contrivedEx4 = user => fromNullable(user.address) .chain(a => fromNullable(a.match(/(d{5})$/i))) .chain(zip => fromNullable(cityByZip(zip))) .fold(() => "can't find city", city => city)
  • 100. const depObjs = b => List(b.deps).flatMap(next => findDependencyByProject(next.Project.name, b.previous.deps) .fold(x => x, found => makeArgs(next, found))) const mapBuildsAndDepsForDiffQueue = (builds) => List(builds) .filter(b => b.previous) .flatMap(b => makeArgs(b, b.previous).concat(depObjs(b))) .filter(b => b) .toJS() const filterExistingDiffs = (items) => List(items).traverse(Task.of, (i) => find(Diff, { BuildId: i.buildId, DiffId: i.prevId, type: i.method }) .map(e => e.swap().getOrElse(null)) .map(bs => bs.filter(x => x).toJS())
  • 101. const buildProject = ({branch, sha}) => queueUnzipWwwOnS3(sha) .chain(() => isReleaseOrMainBranch(branch)) .fold(() => _.noop, () => generateReport(sha) .chain(queueDiffsForTileBuildsAndDeps) .chain(() => getHeadCommit(sha) .fold(() => Task.of(null), head => makeVrtDeployment(head, sha) .chain(() => createPrApp(head, sha)))) .fork(console.error, console.log))
  • 104. const vrtReport = ({sha, email, platforms}) => rejectFinishedPlatformOptions(platforms) .chain(plats => plats.map(gatherScreenshots)) .chain(shots => fromNullable(sha) .fold(() => findLastRef(), () => findBuild({sha})) .chain(ref => renderReport(shots, ref, email))) .fork(e => e, r => r)
  • 106. const getConfig = () => Either.try(fs.readFileSync)('cfg.json') const contrivedEx3 = () => getConfig() .map(JSON.parse) .fold(e => 3000, c => c.port)
  • 107. Safer
  • 109. const ProfileLink = user => <a href={`/users/${u.id}`}>{u.name}</a> const Header = str => <h1>Now Viewing {str}</h1>
  • 110. Component :: a -> JSX
  • 115. const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f(x))) })
  • 116. const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f(x))) }) const Heading = str => <h1>Now Viewing {str}</h1> const Title = Comp(Heading).contramap(s => s.pageName)
  • 117. const Title = Comp(Heading).contramap(s => s.pageName) Title.fold({ pageName: ‘Home', currentUser: { id: 2, name: 'Chris Harrison’ } }) // <h1>Now Viewing Home</h1> const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f(x))) }) const Heading = str => <h1>Now Viewing {str}</h1>
  • 118. const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f(x))) })
  • 119. const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f(x))), concat: other => Comp(x => <div>{g(x)} {other.fold(x)}</div>) })
  • 120. const ProfileLink = user => <a href={`/users/${u.id}`}>{u.name}</a>) const Heading = str => <h1>Now Viewing {str}</h1> const Heading = Comp(Title).contramap(s => s.pageName) const Link = Comp(ProfileLink).contramap(s => s.currentUser) const App = Heading.concat(Link)
  • 121. const ProfileLink = user => <a href={`/users/${u.id}`}>{u.name}</a>) const Heading = str => <h1>Now Viewing {str}</h1> const Heading = Comp(Title).contramap(s => s.pageName) const Link = Comp(ProfileLink).contramap(s => s.currentUser) const App = Heading.concat(Link) App.fold({ pageName: ‘Home', currentUser: { name: 'Chris Harrison’ } }) // <div> // <h1>Now Viewing Home</h1> // <a href="/users/22">Chris Harrison</a> // </div>
  • 122. Reducer :: (a, b) -> a
  • 123. const Reducer = g => ({ fold: g, contramap: f => Reducer((acc, x) => g(acc, f(x))), map: f => Reducer((acc, x) => f(g(acc, x))) })
  • 124. const r = Reducer((acc, x) => acc.concat(x)) .contramap(x => `The number is ${x}`) .map(x => x + '! ') [1,2,3].reduce(r.fold, '') // The number is 1! The number is 2! The number is 3! const Reducer = g => ({ fold: g, contramap: f => Reducer((acc, x) => g(acc, f(x))), map: f => Reducer((acc, x) => f(g(acc, x))) })
  • 125. const Reducer = g => ({ fold: g, contramap: f => Reducer((acc, x) => g(acc, f(x))), map: f => Reducer((acc, x) => f(g(acc, x))) })
  • 126. const Reducer = g => ({ fold: g, contramap: f => Reducer((acc, x) => g(acc, f(x))), map: f => Reducer((acc, x) => f(g(acc, x))), concat: o => Reducer((acc, x) => o.fold(g(acc, x), x)) })
  • 127. const appReducer = Reducer((state, action) => { switch (action.type) { case 'set_visibility_filter': return Object.assign({}, state, { visibilityFilter: action.filter }) default: return state } })
  • 128. const todoReducer = Reducer((state, action) => { switch (action.type) { case 'new_todo': const t = { id: 0, title: action.payload.title } return Object.assign({}, state, { todos: state.todos.concat(t) }) default: return state } })
  • 129. const todoApp = appReducer .concat(todoReducer) .contramap(action => Object.assign({filter: 'all'}, action)) .map(s => Object.assign({}, s, {lastUpdated: Date()}))
  • 130. const todoApp = appReducer .concat(todoReducer) .contramap(action => Object.assign({filter: 'all'}, action)) .map(s => Object.assign({}, s, {lastUpdated: Date()})) todoApp.fold({visibilityFilter: ‘complete'}, {type: ‘set_visibility_filter'}) // { visibilityFilter: 'all', // lastUpdated: 'Sun Aug 21 2016 11:04:48 GMT-0700 (PDT)' }
  • 131. const todoApp = appReducer .contramap(action => Object.assign({filter: 'all'}, action)) .concat(todoReducer) .map(s => Object.assign({}, s, {lastUpdated: Date()})) todoApp.fold({visibilityFilter: ‘complete'}, {type: ‘set_visibility_filter'}) // { visibilityFilter: 'all', // lastUpdated: 'Sun Aug 21 2016 11:04:48 GMT-0700 (PDT)' }
  • 132. Hoc :: Component -> Component
  • 133. const Hoc = g => ({ fold: g, concat: other => Hoc(x => g(other.fold(x))) })
  • 134. const hoc = Hoc(withReducer(‘state', 'dispatch', todoApp.fold, {todos: []})) const Todos = hoc.fold(({ state, dispatch }) => <div> <span>Filter: {state.visibilityFilter}</span> <ul> { state.todos.map(t => <li>{t.title}</li>) } </ul> <button onClick={() => dispatch({ type: 'new_todo', payload: {title: 'New todo'}})}> Add Todo </button> <button onClick={() => dispatch({ type: 'set_visibility_filter' })}> Set Visibility </button> </div> )
  • 135. const App = Heading.contramap(s => s.pageName) .concat(TodoComp) .concat(Link.contramap(s => s.currentUser)) .fold({ pageName: 'Home', currentUser: {id: 2, name: 'Boris' } }) ReactDOM.render(App, document.getElementById('body')) const TodoComp = Component(classToFn(Todos)) const Heading = Component(s => <h1>Now Viewing {s}</h1>) const Link = Component(u => <a href={`/users/${u.id}`}>{u.name}</a>)
  • 137. map = compose = program construction
  • 138. // Functor Box.of(20).map(x => x / 2) // Box(10) // Monad Box.of(true).chain(x => Box.of(!x)) // Box(false) // Monoid Box.of('small').concat(Box.of('pox')) // Box('smallpox') // Applicative Box.of(x => x + 1).ap(2) // Box(3) // Traversable Box.of(3).traverse(Either.of, x => fromNullable(x)) // Right(Box(3)) // Natural transformation eitherToBox(fromNullable(null)) // Box(null)