Functional Influences

Post on 13-Feb-2017

480 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

Transcript

FunctionalinfluencesBran van der Meer, 18-08-2015

Agenda1. Abstraction

2. Currying3. Composition

Abstraction1

Pure function• No other dependencies than it’s

signature• Referentially Transparent• Stateless• Separated from it’s environment• Memoizable (cachable results)• More testable, portable and

parallelizable

Pure functionvar sum = function(left, right) { return left + right;};

sum(1, 2); //=> 3sum(1, 2); //=> 3sum(10, 2); //=> 12

Impure functionvar sumish = function(left, right) { return (left + right) * Math.random();};

sumish(1, 2); //=> ?sumish(3, 5); //=> ?

Impure functionvar Counter = function() { this._c = 0;};Counter.prototype.increment = function() { return ++this._c;};

var c = new Counter;c.increment(); //=> 1c.increment(); //=> 2

Impure functionfunction daysThisMonth() { var date = new Date(); var y = date.getFullYear(); var m = date.getMonth(); var start = new Date(y, m, 1); var end = new Date(y, m + 1, 1); return (end - start) / (1000 * 60 * 60 * 24);}

Pure functionfunction daysInMonth(y, m) { var start = new Date(y, m, 1); var end = new Date(y, m + 1, 1); return (end - start) / (1000 * 60 * 60 * 24);}

Higher-order function• A function that takes another function

as an argument• A function that returns a function• Famous examples: map, filter, reduce

Higher-order functionvar map = function(fn, arr) { var newArr = []; for (var i = 0; i < arr.length; i++) { newArr.push(fn(arr[i])); } return newArr;}

Higher-order functionvar makeAdd = function(left) { return function(right) { return left + right; };};

var add5 = makeAdd(5);add5(10); //=> 15

Currying2

Currying• Postponing giving arguments to a

function• A curried function can take less

arguments than it needs, it’ll wait for the others

• A curried function keeps returning a function when called, until it has all arguments

• Partial application is calling a function with less arguments than it needs

• In the extreme: giving one argument at a time

Manual curryingvar sum = function(left) { return function(right) { return left + right; };};

var sum5 = sum(5);//=> function(right) { return 5 + right }

sum5(7); //=> 12

One argument at a timevar sum = function(left, right) { return left + right;};

sum(5, 8); //=> 13

sum = curry(sum);

var sum5 = sum(5); //=> function() {...}sum5(7); //=> 12

One argument at a timesum = curry(sum);

sum(1, 2, 3) //=> 6

sum(1)(2)(3) //=> 6

Partial applicationsum = curry(sum);

sum(1, 2, 3) //=> 6sum(1)(2)(3) //=> 6sum(1)(2, 3) //=> 6sum(1, 2)(3) //=> 6sum(1, 2, 3) //=> 6

Useful examplevar getProp = function(prop, obj) { return obj[prop];};getProp = curry(getProp);

var people = [ {name: ...}, ... ];

var names = map(getProp('name'), people);

Underscore & lodashvar getProp = _.curry(function(obj, prop) { return obj[prop];});

var names = map(getProp('name'), people); // ?!

A functional libraryvar split = curry(function(pattern, str) { return str.split(pattern);});var filter = curry(function(fn, arr) { return arr.filter(fn);});var test = curry(function(re, str) { return re.test(str);});

Truly functional: Ramda

Another examplevar words = function(str) { return split(' ', str);};

var words = split(' ');

Yet another examplevar filterQs = function(xs) { return filter(function(x) { return test(/q/i, x); }, xs);};

var filterQs = filter(test(/q/i));

Composition3

Composition• Chaining functions to create a new

function• Passing return values from one to the

other• Composition enables pipelining of data

Naive implementationvar compose = function(f, g) { return function(x) { return f(g(x)); };};

Examplevar shout = function(x) { return exclaim(toUpper(x));};

var shout = compose(exclaim, toUpper);

shout('send in the clowns');//=> "SEND IN THE CLOWNS!"

Not referencing data argumentsmap(function(num) { return Math.sqrt(num);}, numbers);

map(Math.sqrt, numbers); // No arguments

Pointfreevar invert = function(x) { return -1 * x; };var negate = compose(invert, Math.abs);var negateAll = map(negate);

negateAll([-1, -2, 0, 2, -3, 4]);//=> [-1, -2, -0, -2, -3, -4]

Another examplevar cars = [ {price: '48000'}, ...];

var averagePrice = compose( average, map(parseInt), map(getProp('price')));

averagePrice(cars); //=> 42000

More? Training!4

top related