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

Post on 08-Jul-2015

342 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Выступление Дмитрия Кириенко и Алексея Осипенко на ноябрьской встрече Донецкого Лямбда-клуба. http://l.dn.ua/ http://dimoneverything.blogspot.com/2013/11/blog-post.html

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);

}

});

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();

if (value.length > 0) {

$("#notice").text(value);

}

});

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);});

$("#login").on("click", function (event)

{

var value = $(event.target).val();

if (value.length > 0) {

$("#notice").text(value);

}

});

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);});

$("#login").on("click", function (event) {

var value = $(event.target).val();

if (value.length > 0) {

$("#notice").text(value);

}

});

var values = $("#login").events("click") .map(chain(pluck('target'), $, method('val')) .filter(nonEmpty);

values.onValue(function (value) { $("#notice").text(value); });

$("#login").on("click", function (event)

{

var value = $(event.target).val();

if (value.length > 0) {

$("#notice").text(value);

}

});

type Stream[a] = [(T, a)]type Box[a] = T -> a

Stream will receive B and C

Box immediately receives A and will receive B and C

A B C

A B C

new Stream( function (sink) {

sink(new Event(10));

sink(new Event(20));

return function() {};

});

Box.nothing(); // empty boxBox.unit(10); // box with constant value of 10Stream.never(); // empty streamStream.unit(10); // stream with immediate value of 10

Stream.error(10); // stream with immediate error of 10Box.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 })

startPosition = cursorPosition.sampledBy mousedowncurrentPosition = cursorPosition.sampledBy mousedrag

# cursorPosition → { x: 112, y: 234 }

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

чо?

top related