"Немного о функциональном программирование в JavaScript" Алексей Коваленко
- 5. Functional JavaScript
1. Imperative and Declarative
Imperative
var numbers = [1,2,3,4,5],
total = 0;
for(var i = 0; i < numbers.length; i++) {
total += numbers[i];
}
console.log(total); //=> 15
- 6. 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
- 8. Functional JavaScript
1. Imperative and Declarative
JavaScript
Multi Paradigm Language, child of Self and Scheme
From Self:
From Scheme
1) Dynamic dispatch
2) Encapsulation
etc.
1) First class functions
2) Closures
- 10. 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
- 11. 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
- 12. 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
- 13. 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
- 17. 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
- 18. 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’]
- 19. 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];
- 24. 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
- 25. 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];
});
- 26. Functional JavaScript
4. Composition
Composition & Curry
var 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
- 31. 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];
- 33. 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)
- 36. 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));
};
- 37. 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"}
- 38. 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
- 40. 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
- 41. 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;
}));
- 42. 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);
- 43. 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}
- 44. 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/