Func up your code
-
Upload
maciej-komorowski -
Category
Software
-
view
205 -
download
0
Transcript of Func up your code
![Page 1: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/1.jpg)
Func up your codeMaciej Komorowski
![Page 2: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/2.jpg)
What is func%onal programming?
![Page 3: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/3.jpg)
Func%onal programming is programming paradigm [...] that
treats computa%on as the evalua%on of mathema&cal func&ons and
avoids changing-state and mutable data.
— Wikipedia
![Page 4: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/4.jpg)
Pillars of FP
• Higher-order func0ons (e.g. map)
• Immutable data
• Lazy evalua0on
• Pure func0ons
• Recursion
![Page 5: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/5.jpg)
Pure func)on! Always evaluates the same result value given the same arguments! Does not cause any seman5cally observable side effect, such as muta5on of mutable objects
![Page 6: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/6.jpg)
Pure func)on examples// Purefunction add(a, b) { return a + b;}
// ImpureMath.random();
// Impureconst items = []
function addItem(item) { return items.push(item);}
![Page 7: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/7.jpg)
State muta(on
![Page 8: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/8.jpg)
State muta(on in OOP
! Relies heavily on encapsula)on! Has hidden nature! Brings nondeterminism! Root cause of doom
![Page 9: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/9.jpg)
Brogrammer1
State muta)on example
A brogrammer is [...] a slang term for a macho, male programmer. A brogrammer
might self-describe as a sociable programmer.
— Wikipedia
1 Frans Hals, Oil on canvas, 1630. Source: classicprogrammerpain;ngs
![Page 10: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/10.jpg)
What brogrammer does?
• drinkBeer
• talk
![Page 11: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/11.jpg)
Stateful implementa*on
class Brogrammer { constructor() { this.beers = 0; }
drinkBeer() { /* ... */ } talk() { /* ... */ }}
![Page 12: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/12.jpg)
Stateful – drinkBeer
it('increment number of drunk beers', () => { expect(brogrammer.drinkBeer()).toEqual(1); expect(brogrammer.drinkBeer()).toEqual(2);});
// Inside Brogrammer classdrinkBeer() { return this.beers += 1; // encapsulates 'beers'}
![Page 13: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/13.jpg)
Stateful – talk testsit('says "Beer me up!" before drinking', () => { expect(brogrammer.talk()).toEqual("Beer me up!");});
it('says "Yummy" after 1st beer', () => { brogrammer.drinkBeer(); expect(brogrammer.talk()).toEqual("Yummy");});
it('says "I a<M dRuNk" after 10th beer', () => { brogrammer.drinkBeer(); // 8 x brogrammer.drinkBeer(); brogrammer.drinkBeer(); expect(brogrammer.talk()).toEqual("I a<M dRuNk");});
![Page 14: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/14.jpg)
Stateful – talk implementa+on
// Inside Brogrammer classtalk() { return ({ 0: 'Beer me up!', 1: 'Yummy', // ... 10: 'I a<M dRuNk', })[this.beers] || '';}
![Page 15: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/15.jpg)
How to remove state?Single source of truth
![Page 16: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/16.jpg)
Naïve stateless – implementa+on
class Brogrammer { constructor(store) { this.store = store; }
// ...}
![Page 17: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/17.jpg)
Naïve stateless – drinkBeer tests
it('increment number of drunk beers', () => { const store = { beers: 0 }; const brogrammer = new Brogrammer(store);
brogrammer.drinkBeer();
expect(store.beers).toEqual(1);});
![Page 18: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/18.jpg)
Naïve stateless – drinkBeer implementa+on
// Inside Brogrammer classdrinkBeer() { return this.store.beers += 1;}
![Page 19: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/19.jpg)
Naïve stateless – talk tests
it('says "I a<M dRuNk" after 10th beer', () => { const store = { beers: 10 }; const brogrammer = new Brogrammer(store);
expect(brogrammer.talk()).toEqual("I a<M dRuNk");});
![Page 20: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/20.jpg)
Naïve stateless – talk implementa+on
// Inside Brogrammer classtalk() { return ({ 0: 'Beer me up!', 1: 'Yummy', // ... 10: 'I a<M dRuNk', })[this.store.beers] || '';}
![Page 21: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/21.jpg)
Solu%on review! Removed state from the Brogrammer! Easier tes2ng" Lost encapsula-on
![Page 22: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/22.jpg)
How to improve?The Redux way
![Page 24: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/24.jpg)
Three Principles of Redux3
! Single source of truth! State is read-only! Changes are made with pure func)ons
3 Source: Redux
![Page 25: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/25.jpg)
Three Principles of ReduxSingle source of truth
console.log(store.getState());
// {// brogrammer: {// beers: 0// }// }
![Page 26: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/26.jpg)
Three Principles of ReduxState is read-only
store.dispatch({ type: 'INCREMENT_BEERS',});
![Page 27: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/27.jpg)
Three Principles of ReduxChanges are made with pure func3ons
function brogrammer(state = {}, action) { switch (action.type) { case 'SET_BEERS': return { ...state, beers: 5, }; // case ... }}
![Page 28: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/28.jpg)
Redux – incrementBeers ac%on
it('returns action with type INCREMENT_BEERS', () => { const action = incrementBeers();
expect(action).toEqual({ type: 'INCREMENT_BEERS' });});
![Page 29: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/29.jpg)
Redux – incrementBeers ac%on
const incrementBeers = () => ({ type: 'INCREMENT_BEERS',});
![Page 30: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/30.jpg)
Redux – brogrammer reducer
it('returns state with incremented beers', () => { const state = { beers: 0 }; const action = incrementBeers();
const nextState = brogrammer(state, action);
expect(nextState).toEqual({ beers: 1 });});
![Page 31: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/31.jpg)
Redux – brogrammer reducerimplementa)on
const brogrammer = (state = {}, action) => { switch (action.type) { case 'INCREMENT_BEERS': return { ...state, beers: state.beers + 1 }; default: return state }}
![Page 32: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/32.jpg)
Redux – drinkBeer tests
it('increment number of drunk beers', () => { const store = createStore({ beers: 0 }); const brogrammer = new Brogrammer(store);
brogrammer.drinkBeer();
expect(store.dispatch) .toHaveBeenCalledWith(incrementBeers());});
![Page 33: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/33.jpg)
Redux – drinkBeer implementa+on
// Inside Brogrammer classdrinkBeer() { return this.store.dispatch(incrementBeers());}
![Page 34: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/34.jpg)
Redux – talk tests
it('says "I a<M dRuNk" after 10th beer', () => { const store = createStore({ beers: 10 }); const brogrammer = new Brogrammer(store);
expect(brogrammer.talk()).toEqual("I a<M dRuNk");});
![Page 35: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/35.jpg)
Redux – talk implementa+on
// Inside Brogrammer classtalk() { return ({ 0: 'Beer me up!', 1: 'Yummy', // ... 10: 'I a<M dRuNk', })[this.store.get('beers')] || '';}
![Page 36: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/36.jpg)
Solu%on review! Easy tes(ng! Be,er separa(on! Explicit state changes! Full control over state
![Page 37: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/37.jpg)
A few thoughts on Redux
![Page 38: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/38.jpg)
Immutable data
![Page 39: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/39.jpg)
Mutable vs immutable// Mutableconst items = ['foo'];
items.push('bar');items.push('baz');
console.log(items); // ["foo", "bar", "baz"]
![Page 40: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/40.jpg)
Mutable vs immutable// Immutable via immutable-jsconst items = Immutable.List.of('foo');
items.push('bar');items.push('baz');
console.log(items.toArray());// ["foo"]
console.log(items.push('bar').push('baz').toArray());// ["foo", "bar", "baz"]
![Page 41: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/41.jpg)
What about performance?5
5 Source: React.js Conf 2015 - Immutable Data and React
![Page 42: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/42.jpg)
Performance benchmarkArray push 1,000,000 items:
var list = [];for (var i = 0; i < 1000000; i++) { list.push(i);}
83 ms
![Page 43: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/43.jpg)
Performance benchmarkMori immutable vector conj 1,000,000 items:
var list = mori.vector();for (var i = 0; i < 1000000; i++) { mori.conj(list, i);}
288 ms
![Page 44: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/44.jpg)
Should update problemconst form = { /* ... */ };
function submit(form) { if (hasChanged(form)) { doSomethingExpensive(form); }}
![Page 45: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/45.jpg)
Should update problemversioning
let currentFormVersion;
function hasChanged(form) { const formVersion = md5(JSON.stringify(form));
return formVersion !== currentFormVersion;}
![Page 46: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/46.jpg)
Should update problemdirty bits
function hasChanged(form) { for (var field in form) { if (field.meta.dirty === true) { return true; } }
return false;}
![Page 47: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/47.jpg)
Should update problemobservable pa+ern
const form = { /* ... */ };
Object.observe(form, changes => { doSomethingExpensive(form);});
form.firstName = 'Maciej';form.lastName = 'Komorowski';form.profession = 'Brogrammer'; // Not true :)
![Page 48: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/48.jpg)
Should update problemimmutable
let currentForm = { /* ... */ };
function hasChanged(form) { return currentForm !== form;}
![Page 49: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/49.jpg)
Memoiza(on examplefunction memoize(fn) { var cache = {}; return function (arg) { var hash = arg === Object(arg) ? JSON.stringify(arg) // Wat? : arg; return hash in cache ? cache[hash] : (cache[hash] = fn.call(this, arg)); }}
![Page 50: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/50.jpg)
Memoiza(on examplefunction rawSum(list) { return list.reduce((a, b) => a + b)}
const sum = memoize(rawSum);const array = [0, 1, ...1000000];
sum(array); // 89 ms
rawSum(array); // 51 mssum(array); // 42 ms
![Page 51: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/51.jpg)
Advantages of immutability! No defensive copies! Can be faster! Be3er for concurrency (no deadlocks)
![Page 52: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/52.jpg)
Explore func-onal programing❗It's worth it
![Page 54: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/54.jpg)
QuizWhat f does?
f = 0 : 1 : zipWith (+) f (tail f)
![Page 55: Func up your code](https://reader033.fdocuments.in/reader033/viewer/2022052514/589b29f61a28ab2d4c8b5c07/html5/thumbnails/55.jpg)
AnswerGenerates Fibonacci sequence
> let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
> take 11 fibs[0,1,1,2,3,5,8,13,21,34,55]