Date post: | 16-Jul-2015 |
Category: |
Internet |
Upload: | natalia-zaslavskaya |
View: | 317 times |
Download: | 1 times |
Agenda
Declarative Vs. Imperative
Functional Programming
Harness ES6 and Lodash
Functional best practices
Declarative ProgrammingDeclarative programming
focuses on the what * * *
Imperative programming focuses on the how
Imperative Codefunction followers(person, data) {
var result = [];
for (var i=0 ; i<data.length ; i++) {
if (data[i].follows.indexOf(person._id) >= 0 ) {
result.push(data[i]);
}
}
return result;
}
Wikipediahttp://en.wikipedia.org/wiki/Function_%28mathematics%29
“In mathematics, a function is a relation between a set of inputs <domain> and a set of permissible outputs <range> with the property that each input is related
to exactly one output.”
Not (Math) Functions
person => person’s child
function add(x) {this.sum += x; return this.sum;
}
function getSum(){return this.sum;
}
Math => Code Advantages of pure (===math style) functions
Constant output per input => Cacheable, Parallelizable
Composable => Single responsibility, Reusability, Great for DSLs
Known domain and range => Simplicity, Consistency
No side effects => Easy to test, Easy to reproduce
Functional Approach
minFollowers = (min, data) => _.where(data, person => followers(person, data) >= min)
maxFollowers = (max, data) => _.where(data, person => followers(person, data) >= max)
rangeFollowers = (min, max, data) => maxFollowers(max, minFollowers(min, data))
Composition & Partial
rangeFollowers = (min, max, data) => _.compose( _.partial(maxFollowers, max), _.partial(minFollowers, min) )
DSLs
minFollowers = (min, data) => followersCount(isMoreThen(min), data)
maxFollowers = (max, data) => followersCount(lessThen(min), data)
rangeFollowers = (min, max, data) => followersCount(inRange(min, max), data)
Isn’t this syntax nice?
DSLs
moreThen = min => (val => val >= min)
lessThen = max => (val => value <= max),
inRange = (min, max) => (val => val>= min && val <= max)
followersCount = (filter, data) => _.where(data, person => filter(getFollowersOf(data, person._id))
It requires this bootstrapping:
So don’t get curried way…
Memoize
// O(2^n)var fib = n => (n<2) ? 1 : fib(n-2) + fib(n-1)
//O(n)var fib = _.memoize(n => (n<2) ? 1 : fib(n-2) + fib(n-1))
Pure functions can be memorised (cached) per input, trading CPU for memory
By default, the first argument is the cache key, but it can be customised
Immutability & Statelessness
setName = (obj, name) => { obj.name = name; }
withName = (obj, name) => _.merge(obj, {name: name})
No mutation, no side effects
Group Common Names
histogram = _(data). groupBy(person => person.name.first). mapValues(people => people.length). transform( (acc, count, name) => acc[count] = _.union(acc[count], [name])). value();
Say we want to create a histogram of people’s names
[{name:{first:’David’, last:’Jones’},…},{name:{first:’David’, last:’Kulas’},…},{name:{first:’Mia’, last:’Angelo’},…},{name:{first:’Lucia’, last:’Stroman’},…}]
{ 1:[‘Lucia’, ‘Mia’] 2:[‘David]}
Group Common *histogram = (data, predicate) => _(data). groupBy(predicate). mapValues(people => people.length). transform( (acc, count, name) => acc[count] = _.union(acc[count], [name])). value();
histogram(data, ’age’)
histogram(data, _.partialRight(followers, data))
So now we can do
Good Ideavar appState = {…} // hidden by closure, class or module
updateData = data => { // privileged method appState.data = data updateView(appState.data, appState.renderSettings, setView) }
updateState = newPartialState => { // privileged method appState = _merge(appState, newPartialState) updateView(appState.data, appState.renderSettings, setView) }goGetData().then(updateData)app.addEvenrListener(‘state-change’, updateState)
Access App State In One Place
Bad Idea
var myFunc = isVery => obscured => (because, i) => (just, learned) => about => functional => programming (and, arrow, notation) => but => maybe => iShould => breakeItDown.toSmaller.functions
Using functional style to make your code obscured