"Немного о функциональном программирование в JavaScript"...
-
Upload
fwdays -
Category
Technology
-
view
459 -
download
2
Transcript of "Немного о функциональном программирование в JavaScript"...
Functional JavaScript
1. Imperative and Declarative
Imperativevar numbers = [1,2,3,4,5], total = 0;
for(var i = 0; i < numbers.length; i++) { total += numbers[i]; }
console.log(total); //=> 15
Functional JavaScript
1. Imperative and Declarative
Declarative
var numbers = [1,2,3,4,5];
var total = numbers.reduce(function(sum, n) { return sum + n; });
console.log(total) //=> 15
Functional JavaScript
1. Imperative and Declarative
Declarative ImperativeJava C/C++SQL Go
PHP PythonHaskell
Prolog
Functional JavaScript
1. Imperative and Declarative
JavaScriptMulti Paradigm Language, child of Self and Scheme
From Self:
From Scheme
1) Dynamic dispatch 2) Encapsulation etc.
1) First class functions 2) Closures
Functional JavaScript
2. Func. Programming Theory
var str = '';
function join(arr) { for (var i = 0, l = arr.length; i < l; i++) { str = str + arr[i]; }
console.log(str); }
join([0,1,2,3]);//-> ‘0123’
console.log(str === ‘0123');//-> true
Functional JavaScript
2. Func. Programming Theory
function join(arr) { var str = ‘';
for (var i = 0, l = arr.length; i < l; i++) { str = str + arr[i]; } return str; }
var joinedArr = join([0,1,2,3]);
console.log(joinedArr === ‘0123');//-> true
Functional JavaScript
2. Func. Programming Theory
function join(arr, index, str) { if (index === arr.length) { return str } return join( arr , (index || 0) + 1 , (str ? str : '') + arr[index || 0] ); }
var joinedArr = join([0,1,2,3]);
console.log(joinedArr === ‘0123');//-> true
TCO => ES6
Functional JavaScript
2. Func. Programming Theory
function join(arr, index, str) { return (index === arr.length) ? str : join(arr ,(index || 0) + 1 ,(str ? str : '') + arr[index || 0] ); }
var joinedArr = join([0,1,2,3]);
console.log(joinedArr === ‘123');//-> true
Functional JavaScript
3.Curry
var add = function (a, b) { return a + b; }
add(1, 2); //-> 3 add(1, 2, 3) //-> 3
add(1); //-> NaN
Functional JavaScript
3.Curry
var add = function (a, b) { return function (b) { return a + b; } }
var result = add(1);
console.log(result);//-> function console.log(result(100));//-> 101
Functional JavaScript
3.Curry
var fn = curry(function(a, b, c) { return [a, b, c]; });
fn(‘a', ‘b', ‘c'); fn(‘a', ‘b’)('c'); fn(‘a’)('b', ‘c'); fn(‘a’)(‘b’)('c'); //=> [‘a’, ‘b’, ‘c’]
Functional JavaScript
3.Curry
var filter = curry(function(fn, arr){ return arr.filter(fn); });
var getOdds = filter(isOdd);
var modulo = curry(function (devisor, devided) { return devided % devisor; });
var isOdd = modulo(2);
console.log(filter(isOdd, [1,2,3,4,5,6])) //-> [1, 3, 5];
console.log(getOdds([10,11,12,13,14])) //-> [11, 13];
Functional JavaScript
4. Composition
var compose = function(f, g) { return function(x) { return f(g(x)); }; };
Simple Javascript composition function
var sine = function(x) { return Math.sin(x) };
var cube = function(x) { return x * x * x };
var sineOfCube = compose(sine, cube);
sineOfCube(10) === sine(cube(10)); //-> true
Functional JavaScript
4. Composition
Composition & Curry
var limit = curry(function(num, data){ return data.slice(0, num); });
var _map = curry(function(fn, arr){ return arr.map(fn); });
var getProp = curry(function(prop, obj){ return obj[prop]; });
Functional JavaScript
4. Composition
Composition & Curryvar users = [ {name: 'Ivan', age: 18}, {name: 'Katya', age: 23}, {name: 'Victor', age: 18}, {name: 'Nata', age: 14}, {name: 'Alex', age: 18}, {name: 'Sveta', age: 34} ];
var usersList = compose(_map(getProp('name')), limit(4));
usersList(users);//-> ["Ivan", "Katya", "Victor", "Nata"]
users{6}users{4}users{4}:name
Functional JavaScript
5. Functor
function addOne(a) { return a + 1; };
addOne(5); //-> 6
addOne([5]); //-> 51
Functional JavaScript
5. Functor
fmap :: (a -> b) -> [a] -> [b]JS map -> Functor Lift
[0, 1, 2, 3].map(addOne); //-> [1, 2, 3, 4];
[addOne(0), addOne(1), addOne(2) ...] //-> [1, 2, 3, 4];
Functional JavaScript
5. Functor
var AnyFunctor = function(val){ if(!(this instanceof AnyFunctor)) return new AnyFunctor(val); this.val = val; };
AnyFunctor.prototype.fmap = function(fn){ return AnyFunctor(fn(this.val)); }
fmap(addOne, AnyFunctor(2)); //-> AnyFunctor(3)
Functional JavaScript
5. Functor
AnyFunctor.prototype.fmap = function(fn){ return AnyFunctor(this.val.map(fn)); }
fmap(addOne, AnyFunctor([0, 2, 3, 4])); //-> AnyFunctor([1, 2, 3, 4]);
Functional JavaScript
5. Functor
var Maybe = function(val) { if (!(this instanceof Maybe)) { return new Maybe(val); } this.val = val; };
Maybe.prototype.fmap = function(f){ return this.val == null
? Maybe(null) : Maybe(f(this.val));
};
Functional JavaScript
5. Functor
var concat = curry(function(foo, bar){ return foo + bar; });
var pluck = curry(function(prop, obj){ return obj[prop]; });
var match = curry(function (reg, str) { return str.match(reg); });
var showLength = compose(concat('The length is: '), pluck('length'));
var getWords = compose(Maybe, match(/\w+/g));
var program = compose(fmap(showLength), getWords);
var result = program('Hello world'); //-> Maybe {val: "The length is: 2"}
Functional JavaScript
5. Functor
var match = curry(function (reg, str) { return str.match(reg); });
getWords('Hello World') //-> Maybe {val: ['Hello', 'World']} getWords() //-> Maybe {val: null}
var getWords = compose(fmap(match(/\w+/g)), Maybe);
compose(
fmap(match(/\w+/g)),
Maybe
);
String | null
Maybe { val: String | null, fmap: fn
}
Maybe.fmap(match(reg))
Maybe { val: match(reg)(String)
}
Maybe { val: null
}
String
null
Functional JavaScript
6. Ramda
Underscore / Lodash
var map = R.map(function(n) { return n * 2; });
map([1, 2, 3]);
_.map([1, 2, 3], function(n) { return n * 2; });
Ramda
R.map(function(n) { return n * 2; }, [1, 2, 3]);
data function
datafunction
Functional JavaScript
6. Ramda
Underscore / Lodash
var users = [ { 'user': 'Alex', 'age': 36 }, { 'user': 'Ivan', 'age': 40 }, { 'user': 'Ted', 'age': 1 } ];
var youngest = _.chain(users) .sortBy('age') .map(function(chr) { return chr.user + ' is ' + chr.age; }) .first() .value();
var youngest = _.first(_.map(_.sortBy(users, 'age'), function(ch){ return chr.user + ' is ' + chr.age; }));
Functional JavaScript
6. Ramda
Ramda
var sorted = R.sortBy(R.prop('age')); var transformed = R.map(mapFn); var getOne = R.take(1); var program = R.compose(transformed, getOne, sorted); var youngest = program(users);
var mapFn = function(chr){ return chr.user + ' is ' + chr.age; };
console.log(sorted(users)); console.log(transformed(users)); console.log(getOne(users));
console.log(youngest);
Functional JavaScript
6. Ramda
Ramda
var capitalize = R.compose( R.map(R.toUpper), R.map(R.prop('textContent')), Maybe, R.bind(document.getElementById, document) );
// String -> DOMElement// Object -> Maybe Object
// Maybe Object -> Maybe String// Maybe String -> Maybe String
<div id="elementId">Hello World</div>
capitalize('elementId'); //-> Maybe {val: "HELLO WORLD", map: function}
capitalize('elementId2'); //-> Maybe {val: null, map: function}
Links
Taking Things Out of Context: Functors in JavaScript: http://mattfield.github.io/javascript/2013/07/28/taking-things-out-of-context-functors-in-javascript/
Functors, Applicatives, And Monads In Pictures: http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Hey Underscore, You're Doing It Wrong!: https://www.youtube.com/watch?v=m3svKOdZijA
Functional programming patterns for the non-mathematician (cut): https://www.youtube.com/watch?v=AvgwKjTPMmM https://github.com/DrBoolean/patterns_talk
Functional JavaScript, Part 4: Function Currying: http://tech.pro/tutorial/2011/functional-javascript-part-4-function-currying
Introducing Ramda: http://buzzdecafe.github.io/code/2014/05/16/introducing-ramda/