Everything is Composable (Victor Martins)
-
Upload
concrete -
Category
Technology
-
view
96 -
download
2
Transcript of Everything is Composable (Victor Martins)
Everything is composable
Hello!I am Victor Igor
You can find me at @victorvoid
1.Programming paradigms
A “new” perspective on modeling the flow of your software.
“Na prática, cada paradigma vem com a sua própria maneira de pensar, e há problemas para os quais é a melhor abordagem.
Programming paradigms
◍ Functional programming◍ Object-oriented programming◍ Logic programming◍ Symbolic programming
Composability The essence of software development is composition.
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
Composability
const doin_Thangs = str => _.chain(str) .words() .groupBy(s => s.length) .orderBy(x => x.length) .take(2) .flatten() .value()
Composability
const reactiveUpInHere = el => fromEvent(el, 'keyup') .map(e => e.target.value) .filter(text => text.length > 2) .throttle(500) .distinctUntilChanged()
Composability
(->> (range 1000000000000000000) (filter even?) (map inc) (take 5) (partition 2 1)) ;;=> ((1 3) (3 5) (5 7) (7 9))
Composability
player.unitWithinRange(2).where(UnitIs.Enemy).where(UnitIs.Tank).DoDamage(5)
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
‘Victor and Igor’
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
‘victor and igor’
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
[‘victor’,‘and’,‘igor’]
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
[‘victor’,‘and’,‘igor’]
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
[‘igor’,‘and’,‘victor’]
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
[‘igor’,‘victor’]
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
‘igorvictor’
Composability
const doThing = 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('')}
Composability
const doThing = 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('')}
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
Composability
Composability
“O maior contribuinte de complexidade em muitos sistemas é o tratamento do estado e
o peso que isso acrescenta ao tentar analisar um sistema.”
Ben Moseley & Peter MarksOut of the Pit 2006
Control flow
Composability
Composability
Code volume
Composability
Composability
Composability
Composability
const dotChainy = str =>str .toLowerCase() .split(' ') .map(c => c.trim()) .reverse() .filter(x => x.length > 3) .join('')
Programming !== Math
Programming !== Math
Programming !== Math
try { return f(x)} catch(e) { console.error(e)}
Programming !== Math
if { return f()} else(e) { return y}
Programming !== Math
let stuff = [1, 2, 3]stuff = [1, 2]
Programming !== Math
let stuff.splice(0, 2) stuff.pop()
Programming !== Math
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++;}
Assignment
CallbacksLoops
Side EffectsBranching
Errors
Programming !== Math
Programming !== Math
Programming != Math
Programming !== Math
f.g
Programming !== Math
f.g = x => f(g(x))
Programming !== Math
str.toUpperCase().trim()
Programming !== Math
trim(toUpperCase(str))
Category theory
Category Theory
What’s category theory?
What’s category theory?
Category Theory
Categories represent abstraction of other mathematical concepts.
A mudança de paradigma provocada pela teoria da relatividade de Einstein trouxe a constatação de que não há uma perspectiva única para ver o mundo.
Category
Category Theory
objects
Category
Category Theory
objects
Arrows or morphisms
Category
Category Theory
objects
Arrows or morphisms
Domain
dom(f) f
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
dom(f) f
cod(f)
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
dom(f)
g
cod(f)
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
f
Composition
h
Category
Category Theory
objects
Arrows or morphisms
Domain/codomain
f
Composition
hh . f
Category
Category Theory
objects
Arrows or morphisms
Domain/codomainCompositionIdentity
World Wide Web
Category Theory
World Wide Web
Category Theory
objects = webpages
Arrows = hyperlinks
World Wide Web
Category Theory
objects = webpages
Arrows = hyperlinks
Composition = Links don’t composeIdentity
World Wide Web
Category Theory
objects = nodes
Arrows = edges
Composition = Edges don’t composeIdentity
Graphs
Category Theory
objects = sets (or types)
Arrows = functions
Composition = function compositionIdentity = identity function
Programming
Functors
Category Theory
Category Theory
Functors map between categories
Functors
Category Theory
A BCategory Category
FunctorF
Category Theory
Composition Law
F(g ∘ f) = F(g) ∘ F(f)Identity Law
F(idA) = idF(A)
Functors laws
Category Theory
“Hey, I know what can be mapped over. An array can be mapped over — you can map a function over an array!”
Category Theory
Identity
const f = [1,2,3]f.map(x => x) //[1,2,3]
Category Theory
Composition
[1,2,3].map(x => f(g(x)))
= [1,2,3].map(g).map(f)
Composability
const nextCharForNumberString = str => { const trimmed = str.trim() const number = parseInt(trimmed) const nextNumber = number + 1 return String.fromCharCode(nextNumber)}
nextCharForNumberString(' 70 ') //'G'
Composability
const nextCharForNumberString = str => return [str.trim()]
.map(trimmed => new Number(trimmed)) .map(number => number + 1) .map(n => String.fromCharCode(n))
nextCharForNumberString(' 70') //['G']
Category Theory
Build your own Functor
Composability
const Box = x => ({ map: f => Box(f(x))})
const Box = x => ({ map: f => Box(f(x))})
const nextCharForNumberString = str => return Box(str.trim())
.map(trimmed => new Number(trimmed)) .map(number => number + 1) .map(n => String.fromCharCode(n))
nextCharForNumberString(' 70') //Box('G')
const Box = x => ({ map: f => Box(f(x)), fold: f => f(x)})const nextCharForNumberString = str => return Box(str.trim())
.map(trimmed => new Number(trimmed)) .map(number => number + 1) .fold(n => String.fromCharCode(n))
nextCharForNumberString(' 70') //'G'
Assignment
CallbacksLoops
Side EffectsBranching
Errors
Loops
filtermap
reduce
Assignment
CallbacksLoops
Side EffectsBranching
Errors
CallbacksSide effects
Promise(5).then(five => five + 2)//Promise(7)
Promise(5).then(five => Promise(five + 2))//Promise(7)
Promise(5).map(five => five + 2))//Promise(7)
const doThing = () => fs.readFile('file.json', 'utf-8', (err, data) => { if(err) throw err const newdata = data.replace(/8/g, '6') fs.writeFile('file2.json', newdata, (err, _) => { if(err) throw err console.log('success!') } }
const readFile = futurize(fs.readFile)const writeFile = futurize(fs.writefile)
const doThing = () => readFile('file.json') .map(data => data.replace('/8/g', '6') .chain(replaced => writeFile('file2.json', replaced))
const readFile = futurize(fs.readFile)const writeFile = futurize(fs.writefile)
const doThing = () => readFile('file.json') .map(data => data.replace('/8/g', '6') .chain(replaced => writeFile('file2.json', replaced))
doThing().fork(e => console.log(e), r => console.log('success'))
const lib = username => getTweets(username) .map(tweets => truncateTo130(tweets)) .chain(tweets => writeFile('tweets.json', tweets))
lib('@victorvoid').chain(f => saveToS3(f)).fork(e => console.error(e), r => console.log(r))
Assignment
CallbacksLoops
Side EffectsBranching
Errors
ErrorsBranching
Either
data Either a b = Left a | Right b
Left('no loaded').fold(() => 'uow, error!', s => s.toUpperCase())//'uow, error!'
Right('loaded').fold(() => 'uow, error!', s => s.toUpperCase())//'LOADED'
LeftOrRight('no loaded') .fold(() => 'uow, error!', s => s.toUpperCase())
Right(2) .map(x => x + 4) .map(x => x / 2) .fold(() => 'uow, error!', r => r + 1)//4
Left('ignored') .map(x => x + 4) .map(x => x / 2) .fold(() => 'uow, error!', r => r + 1)//'uow, error!'
const getConfig = () => { try { return fs.readFileSync('config.json') } catch (e) { return null }}const getPort = () => { const str = getConfig() if(str) { const parsed = JSON.parse(str)
return parsed.port } else (e) { return 3000 }}
const getConfig = () => Either.try(fs.readFileSync)('config.json')
const getPort = () => getConfig() .map(JSON.parse) .fold(e => 3000, c => c.port)
const getThing = 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 'cant find city' } } } return 'cant find city'}
const getThing = user => fromNullable(user.address) .chain(a => fromNullable(a.match(/(\d{5})$/i))) .chain(zip => fromNullable(cityByZip(zip))) .fold(() => 'cant find city', city => city)
Assignment
CallbacksLoops
Side EffectsBranching
Errors
React example
Component :: a -> JSX
a JSX bf g
a JSX bf g
a JSXfb
g
const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f(x)))})
const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f))})
const heading = str => <h1>You are viewing {str}</h1>
const Title = Comp(heading).contramap(s => s.pageName)
const Comp = g => ({ fold: g, contramap: f => Comp(x => g(f))})
const heading = str => <h1>You are viewing {str}</h1>
const Title = Comp(heading).contramap(s => s.pageName)
Title.fold({ pageName: 'Home', currUser: {id: '123', name: 'Victor'}})//<h1>You are viewing Home</h1>
Learn a new language
Fantasy Land Specification
References- Mostly-adequate-guide- Professor-frisby-introduces-composable-functional-javascript- Ramda-fantasy- Functors, Applicatives, And Monads In Pictures- Bartosz Milewski - Category Theory for programmers
Thanks!Any questions?
You can find me at @victorvoid & victorvoid.me