"Немного о функциональном программирование в...

45
Functional JavaScript Alexey Kovalenko Wix [email protected] https://github.com/xxllexx

Upload: fwdays

Post on 18-Jul-2015

461 views

Category:

Technology


2 download

TRANSCRIPT

Functional JavaScript

Alexey Kovalenko Wix

[email protected] https://github.com/xxllexx

Functional JavaScript

Imperative & Declarative

Functional JavaScript

1. Imperative and Declarative

What and HowImperative

Declarative

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 Programming Theory

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

Curried functions

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

Developed by Haskell Brooks Curry

curry(f) -> X-> ( Y -> (Z ->N) )

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

3.Curry

Lodash: _.curryWu.js: wu.autoCurry Ramdajs: R.curry

Composition (Category Theory)

Functional JavaScript

4. Composition

Composition

A B

C

g

ff ∘ g

f ∘ g = f(g(x))

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

Functors

Functional JavaScript

5. Functor

function addOne(a) { return a + 1; };

addOne(5); //-> 6

addOne([5]); //-> 51

Functional JavaScript

5. Functor

fmap :: (a -> b) -> f a -> f bclass (typeclass) Functor f where

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 fmap = curry(function(f, obj) { return obj.fmap(f); });

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

Functor Maybe

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

Ramda“a practical functional library for Javascript programmers.”

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/

Thank You!