Upload
the-software-house
View
320
Download
2
Embed Size (px)
Citation preview
O MNIEBlog: Na co dzień PHP i JSInspirują mnie inne języki programowania i podejścia
http://wiktortoporek.name/blog
var grades = [5, 5, 4, 3, 4, 2];var sum = 0;for (var i in grades) { sum += grades[i];}var avg = sum / grades.length;
var grades = [5, 5, 4, 3, 4, 2];var sum = grades.reduce( function(currentSum, currentGrade) { return currentSum + currentGrade; });var avg = sum / grades.length;
[5,5,4,3,4,2] → 23
REAGOWANIE NA KLAWISZ ENTERvar keydown = Rx.Observable.fromEvent(document, 'keydown');keydown.forEach( function(event) { if (event.which === 13) { // do something } });
Elastyczniej:var keydown = Rx.Observable.fromEvent(document, 'keydown');var enterPresses = keydown.filter( function(event) { return event.which === 13; });enterPresses.forEach(function() {/* do something */});
M↓ M↓ M⇝ M⇝ M⇝ M⇝ M⇝ M⇝ M⇝ M↑ M↑var mousedown = Rx.Observable.fromEvent(dragTarget, 'mousedown');var mousemove = Rx.Observable.fromEvent(document, 'mousemove');var mouseup = Rx.Observable.fromEvent(dragTarget, 'mouseup' );
var mousedrag = mousedown.flatMap( function (md) { // calculate offsets when mouse down var startX = md.offsetX, startY = md.offsetY;
// Calculate delta with mousemove until mouseup return mousemove.map(function (mm) { mm.preventDefault();
return { left: mm.clientX - startX, top: mm.clientY - startY }; }).takeUntil(mouseup); });
mousedrag.forEach(function(newPosition) { // change element position});
Trochę elastyczniej...
...ale nie do końca
var name = "Doge"function printIt(name) { console.log("Hello " + name);}
printIt(name);
printIt("Bye Doge"); // Hello Bye Doge
Osobna funkcja do witania:function greeting(name) { return "Hello " + name;}
Użycie:var name = "Doge";printIt(greeting("Doge")); // Hello Doge
POŁĄCZMY DWIE FUNKCJE W JEDNĄKlasyczną drogą:
var name = "Doge";function greet(name) { printIt(greeting(name));}greet(name);
Drogą FP:var name = "Doge";var greet = compose(printIt, greeting);greet(name);
A co z parametrem innego typu?var user = { id: 123, name: "Doge"};
To:greet(user); // Hello [object Object]
Dopiszmy kolejną funkcję:function printIt(name) { console.log(name);}function greeting(name) { return "Hello " + name;}function getName(user) { return user.name;}
Skomponujmy nową ze wszystkich trzech:var greetUser = compose(printIt, greeting, getName);var user = { id: 123, name: "Doge"};greetUser(user);
Nie musimy ograniczać się do własnych funkcji:function getFullname(person) { return [person.firstName, person.lastName].join(' ');}
var getFullnameFromJson = compose(getFullname, JSON.parse);
Przykład startowy
Użycie:
function sendMessage(from, to, message) { console.log([from, ' -> ', to, ': ', message].join(""));}
sendMessage('John', 'Alice', 'Hello!'); //John -> Alice: Hello!
Jako John:sendMessage('John', 'Alice', 'Hello!');sendMessage('John', 'Alice', 'How are you?');sendMessage('John', 'Bob', 'Hello!');
Ułatwmy Johnowi:function sendMessageFromJohn(to, message){ sendMessage('John', to, message);}
sendMessageFromMe('Alice', 'Hello!');sendMessageFromMe('Alice', 'How are you?');sendMessageFromMe('Bob', 'Hello!');
Ręczny Curryingfunction sendMessage(from) { return function(to) { return function(message) { console.log([from, ' -> ', to, ': ', message].join("")); } }}
Użycie:var sendMessageFromMe = sendMessage(currentUser);sendMessageFromMe('Alice')('Hey');
Currying z Lodashvar sendMessage = _.curry( function(from, to, message) { console.log([from, ' -> ', to, ': ', message].join("")); });
Użycie:var sendMessageFromMe = sendMessage(currentUser);sendMessageFromMe('Alice', 'Hey');
[TASK].[ASSIGNED_COMPANY_LOGO_URL]
[TASK] → [ASIGNEE] → [COMPANY] → [LOGO] → [URL]
function getTaskCompanyLogoUrl(task){ return task.asignee.company.logo.url;}
Klasycznie:function getTaskCompanyLogo(task){ if (task.asignee !== null) { if (task.asignee.company !== null) { if (task.asignee.company.logo !== null) { return task.asignee.company.logo.url; } } }
return null;}
task → getAsignee → getCompany → getLogo → getUrl
task → stop if null → getAsignee → stop if null → ... → getUrl
MONADOWY PLAN:Value - Bieżemy wartość[ Value ] - Opakowujemy ją[ Value ].map(f).map(f)... - Dowiązujemy pewne operacje[ Value ].getValue() - Odpakowujemy nową wartość
Przykład z pomocą Monet.js*:function getTaskCompanyLogo(task){ var maybeCompanyLogoUrl = Maybe.of(task) .map(getAsignee) .map(getCompany) .map(getLogo) .map(getUrl);
return maybeCompanyLogoUrl.val;}
* fork vViktorPL/monet.js z drobną zmianą na potrzeby prezentacji
Gettery:function getCompany(object) { return object.company;}function getLogo(object) { return object.logo;}function getUrl(object) { return object.url;}
ES6:function getTaskCompanyLogo(task){ var maybeCompanyLogoUrl = Maybe.of(task) .map(task => task.asignee) .map(asignee => asignee.company) .map(company => company.logo) .map(logo => logo.url);
return maybeCompanyLogoUrl.val;}
JAK TO DZIAŁA?Maybe = Some | None
Some.map(f) => { var result = f(this.val); if (result !== null) { return Some(result); } else { return None; }}
None.map(f) => None
Angularowe $q
Źródło: https://docs.angularjs.org/api/ng/service/$q
function asyncGreet(name) { // perform some asynchronous operation, resolve or reject the promise when appropriate. return $q(function(resolve, reject) { setTimeout(function() { if (okToGreet(name)) { resolve('Hello, ' + name + '!'); } else { reject('Greeting ' + name + ' is not allowed.'); } }, 1000); });}
function asyncGreet(name) { ...}
var promise = asyncGreet('Robin Hood');promise.then(function(greeting) { alert('Success: ' + greeting);}, function(reason) { alert('Failed: ' + reason);});
var promise = asyncGreet(name); - Opakowanie wartościpromise.then() - .map()?greeting - wyłuskana nowa wartość
PODSUMOWANIEFunkcje wyższych rzędów takie jak map czy filterułatwiają przetworzenie serii danychKompozycja umożliwia w łatwy sposób składanie kilkufunkcji w jednąCurrying może przydać się do funkcji które przyjmująwiele argumentówMonada to warstwa abstrakcji która sama decyduje w jakisposób wykona przekazane jej operacje
MOJE WNIOSKIWzorce z FP da się odnaleźć w OOFP rzuca inne światło na niektóre problemyProgramowanie czysto funkcyjne jest szaleństwem dlaaplikacji z życia wziętych (potrzebujemy stanu prędzej czypóźniej)FP jest źle "sprzedawane"FP można łączyć z OO