David Dao
Technical University Munich
Refactored:
https://github.com/emepyc/tnt.tree (BioJS Tree Component)
https://github.com/pasierb/flickr-gallery (Flickr Gallery)
Some more components ...
FRP Created:
http://daviddao.github.io/functional-vis-example/src/table.html
- What is Functional Programming?
- Pure Functions / Functionals
- Function Compositions
- Currying
- Partials
- Concept
- Example Applications
How do we get there?
Turing Machine Style
Lambda Calculus Style
Express the result in terms of the inputs, rather than starting from the input and crafting your way to the result
Express what the program should do,
not how
http://www.slideshare.net/ScottWlaschin/fp-patterns-buildstufflt
Definition
Functional programming is a programming paradigm, that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data (Pure functions).
It is a declarative programming paradigm, which means programming is done with expressions.
Source: http://en.wikipedia.org/wiki/Functional_programming
// Original method
var members = [];
for(var i = 0, len = nodes.length; i < len; i++) {
// up until here all 'how'
// the isMember bit is the only thing specific
// everything else generic to all filters
if(nodes.isMember) {
members.push(node);
}
}
Loops describes HOW not WHAT we have to do to get D.
Result: A lot of boilerplate code!
// Refactored
var isMember = function(u) { return u.isMember };
var members = nodes.filter(isMember);
Split the filtering code from the filter.
Takes a data array and a function returning a boolean. Returns a transformed data array.
// extracting some data from each node
var nodes_names = nodes.map(function(node) { return node.name });
// a calculation for each node
var distanceFromMeanBranchLength = nodes.map(function(node) {
return Math.abs(node.branchLength - meanBranchLength);
});
Have some As, want some Bs
Common tasks: access all els properties
Map: [A], (A -> B) -> [B]
// simple arithmetic
var totalDistance = nodes.reduce(function(sum,node) {
return sum + node.branchLength
},0);
// creating strings
var userList = users.reduce(function(html,user) {
return html + "<li>" + user.name + "</li>"
},"");
Have a list of As, create a single B from them
Reduce: [A], (A -> B) -> B
Recursive, we return a B at every stage
fold: we're folding the list down to one thing
// Functional method
function index(obj,i) {return obj[i]}
'a.b.c'.split('.').reduce(index, {a: {b: {c: "hello!"}}}) // => "hello"
filter: [A], (A -> Boolean) -> [A]
map: [A], (A -> B) -> [B]
reduce: [A], (A -> B) -> B
some: [A], (A -> Boolean) -> Boolean
every: [A], (A -> Boolean) -> Boolean
forEach: [A], (A -> Any) -> undefined
Definition
Function composition is the pointwise application of one function to
the result of another to produce a third function.
var compose = function(f,g) {
return function(x) {
return f(g(x));
};
};
var toUpperCase = function(x) { return x.toUpperCase(); };
var exclaim = function(x) { return x + '!'; };
var shout = compose(exclaim, toUpperCase);
shout("functional composition rocks");
//=> "FUNCTIONAL COMPOSITION ROCKS!"
Advantages
More readable
More reusable
Separate logical tasks
Like Lego blocks, rather than Jenga tower
Call a function with fewer arguments than it expects. It returns a function that takes the remaining arguments.
if(!someThingImportant) {
var someThingImportant = {};
}
// this works due to hoisting and function scope
Scope is only affected by functions, not blocks.
Each function defines new scope and has access to parent's scope
Inside its closure, the function is stored with its initialising environment
(function() {
var c = "now you see me";
(function() {
// can see c here
console.log(c);
})();
})();
// c not set here
function makeClosure(name) {
return function () {
return name;
};
}
var description1 = makeClosure("Cloe the Closure");
var description2 = makeClosure("Albert the Awesome");
console.log(description1());
console.log(description2());
var add = function(a, b, c){ return a + b + c }
add(1, 2, 3) //= 6
add(1, 2, 3, 'IGNORE ME') //= 6
add(1) //= NaN
var curry_add = function(a){
return function(b) {
return function(c) {
return a + b + c;
}
}
}
curry_add(1)(2)(3); //=6
var curry_add1 = curry_add(1);
curry_add1(2)(3) //= 6
// Curried get method
var get = function(property, object){
return function(property){
return object[property]
}
}
var obj = [{ id: 1 }, { id: 2 }, { id: 3 }];
obj.map(get('id')) //= [1,2,3]
// Even better with curried map method
var getIDs = map(get('id'));
getIDs(obj); //= [1,2,3]
https://github.com/pasierb/flickr-gallery
Great libraries with FP support:
Underscore
Lodash
Ramda
Advantage : Steal some tricks from math to improve performance of your code (and show off)
Disadvantage: Sometimes confusing for non-math wiz
var unCube = Math.pow.partial(___,1/3);
unCube(27); //3
unCube(15); //2.46621207433047
var later = timeOut.partial(___,1000);
later(alert("here I am!"));//... ... "here I am!"
Returning a new function, where partial arguments are fixed.
function add(a, b) {
return a + b;
}
var addOne = add.bind(null, 1);
addOne(2) // => 3
[1, 2, 3].map(addOne) // => [2, 3, 4]
Function.prototype.bind is a pure JS Solution
Takes a function, returns a new version with more context
Sets this context, and some arguments (left to right)
Can be used to flatten callback hells
// Original code
function updateData(req,res) {
getUser(res.params.userId,function(err,user) {
if(err) return res.send(404);
getProfile(user,function(err,profile) {
if(err) return res.send(500);
updateProfile(user,profile,req.params.profile,function(err) {
if(err) return res.send(500);
});
})
})
}
// Pure JS Solution
function updateProfile(req,res) {
getUser(res.params.userId,function(err,user) {
// bind the user context, returning a fn that
// just needs err and profile
getProfile(user,updateProfileWithUserAndProfile.bind(null,user));
})
}
function updateProfileWithUserAndProfile(user,err,profile) {}
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
Functional
On top of that, you are given an amazing toolbox of functions to combine, create and filter any of those streams.
Event based
Stream based
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
https://gist.github.com/staltz/868e7e9bc2a7b8c1f754
Advantages
Everything can be an event stream
Plugin style coding - high abstraction
Declarative style instead of control flow
Functional programming as powerful modification tool to produce clean code
Disadvantages
Requires to think reactively
Radically different from object oriented design
Mathematical instead of understandable code