• Share
  • Email
  • Embed
  • Like
  • Save
  • Private Content
Функциональное реактивное программирование
 

Функциональное реактивное программирование

on

  • 391 views

Выступление Дмитрия Кириенко и Алексея Осипенко на ноябрьской встрече Донецкого Лямбда-клуба. ...

Выступление Дмитрия Кириенко и Алексея Осипенко на ноябрьской встрече Донецкого Лямбда-клуба.

http://l.dn.ua/
http://dimoneverything.blogspot.com/2013/11/blog-post.html

Statistics

Views

Total Views
391
Views on SlideShare
391
Embed Views
0

Actions

Likes
1
Downloads
0
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Функциональное реактивное программирование Функциональное реактивное программирование Presentation Transcript

    • Javascript unleashed
    • Функциональное программирование объединяет гибкость и мощь абстрактной математики с интуитивной понятностью абстрактной математики
    • function Counter(element) { var that = this; this.count = 0; this.clicked = function () { this.count += 1; } $(element).click(function() { return that.clicked(); }); };
    • $("#login").on("click", function (event) { var value = $(event.target).val(); if (value.length > 0) { $("#notice").text(value); } });
    • $("#login").on("click", function (event) { var value = $(event.target).val(); if (value.length > 0) { $("#notice").text(value); var clickE = $("#login").events("click"); clickE.onValue(function (event) { var value = $(event.target).val(); if (value.length > 0) { $("#notice").text(value); } }); } });
    • $("#login").on("click", function (event) { var value = $(event.target).val(); var clickE = $("#login").events("click"); var values = clickE.map(function (event) { return $(event.target).val(); }); var nonEmptyValues = values.filter(function (value) { return value.length > 0; }); nonEmptyValues.onValue(function (value) { $("#notice").text(value); }); if (value.length > 0) { $("#notice").text(value); } });
    • $("#login").on("click", function (event) { var value = $(event.target).val(); var values = $("#login").events("click") .map(function (event) { return $(event.target).val(); }).filter(function (value) { return value.length > 0; }); values.onValue(function (value) { $("#notice").text(value); }); if (value.length > 0) { $("#notice").text(value); } });
    • $("#login").on("click", function (event) { var values = $("#login").events("click") .map(chain(pluck('target'), $, method('val')) .filter(nonEmpty); values.onValue(function (value) { $("#notice"). text(value); }); var value = $(event.target).val(); if (value.length > 0) { $("#notice").text(value); } });
    • type Stream[a] = [(T, a)] type Box[a] = T -> a A B C Stream will receive B and C A B C Box immediately receives A and will receive B and C
    • new Stream( function (sink) { sink(new Event(10)); sink(new Event(20)); return function() {}; });
    • Box.nothing(); Box.unit(10); Stream.never(); Stream.unit(10); // // // // empty box box with constant value of 10 empty stream stream with immediate value of 10
    • Stream.error(10); // stream with immediate error of 10 Box.error(10); // box with constant error of 10
    • Stream.later(1000, 10); // in a second pops out 10
    • $('input').stream('keyup'); // stream with keyup events
    • asyncCall(data, function (response) { // You have response from your asynchronous call here. }, function (err) { // if the async call fails, the error callback is invoked });
    • asyncCall(data,function(response){ // You have response from your asynchronous call here. }, function(err){ // if the async call fails, the error callback is invoked }); var promise = asyncCall(data); promise.done(function(response){ // You have response from your asynchronous call here. }).fail(function(err){ // if the async call fails, you have the error response here. });
    • Stream.fromPromise($.ajax(params)); // pops a success event on successful response // or the error event on error response
    • _.map([1, 2, 3], function (x) { return x*x; }); // returns [1, 4, 9]
    • _.map([1, 2, 3], function (x) { return x*x; }); // returns [1, 4, 9] priceValue.map(function(x) { return x > 1000; });
    • priceValue.filter(function(x) { return x >= 1000; });
    • _.flatMap(users, function (user) { return user.comments(); }); // returns flat list of all the comments the users have
    • var requests = usernames.map(function(u) { return { url: "/check-username/" + u; } }); requests.flatMap(function (params) { return Stream.fromPromise($.ajax(params)); }); // usernames => "John", "Peter" // requests => {"url": "/check-username/John"}, ... // flatMap => {correct: true}, {correct: false}
    • Stream.prototype.map = function (f) { return this.flatMap(function (x) { return Stream.unit(f(x)); }); } Stream.prototype.filter = function (f) { return this.flatMap(function (x) { if f(x) { return Stream.unit(x); } else { return Stream.nothing(); } }); }
    • password.map2(passwordConfirmation, function(l, r) { return l == r; });
    • Box.prototype.map2 = function (other, f) { return this.flatMap(function (x) { return other.map(function (y) { return f(x, y); }); }); }
    • Box.prototype.apply = function (other) { return this.map2(function (f, x) { return f(x); } ); }
    • var id = function (x) { return x; } Stream.merge = function (streams) { return Stream.fromList(streams).flatMap(id); }
    • var inc = plusClicks.map(function() { return 1; }); var dec = minusClicks.map(function() { return -1; }); var change = plus.merge(minus);
    • Stream.prototype.debounce = function (delay) { return this.flatMapLast(function (value) { return Stream.later(delay, value); }); }
    • Box.prototype.sampledBy = function (sampler) { var that = this; return sampler.flatMap(function () { return that.take(1); }); }
    • votes.take(10); hp.takeWhile(function (hp) { return hp > 0; } ); mousemove.takeUntil(escapePressed);
    • потоки событий мыши
    • mousedown = $(document).stream('mousedown', '.item') mouseup = $(document).stream('mouseup') mousemove = $(document).stream('mousemove')
    • mousedrag = mousedown.flatMapLast( (e)-> mousemove.takeUntil(mouseup) )
    • позиции курсора
    • cursorPosition = mousemove.box().map( (e)-> { x: e.clientX, y: e.clientY } )
    • # cursorPosition → { x: 112, y: 234 } startPosition = cursorPosition.sampledBy mousedown currentPosition = cursorPosition.sampledBy mousedrag
    • shiftPosition = startPosition.zip(currentPosition) .map((s, m)-> { left: m.x-s.x, top: m.y-s.y } )
    • shiftPosition.onValue( (pos)-> $('.item').css(pos) )
    • mousedown.onValue (e)-> e.preventDefault()
    • newPosition = mousedown.flatMapLast (md)-> target = $(md.target); {left, top} = target.offset(); [startX, startY] = [md.clientX - left, md.clientY - top] mousemove.map (mm)-> target: target left: mm.clientX - startX top: mm.clientY - startY .takeUntil mouseup
    • чо?