Futures and promises

May 7, 2014 Overview

Overview ■ Futures in Clojure

Javascript/JQuery

Scala/Akka futures

2 / 15 Overview

Clojure Future Future (example) Future (mechanics) Promises

Javascript/JQuery

Scala/Akka futures Clojure

3 / 15 Future

Overview ■ Future: evaluates a body of code in another thread Clojure Future (def long-calculation Future (example) (future (apply + (range 1e8)))) Future (mechanics) Promises ◆ returns immediately Javascript/JQuery Scala/Akka ■ futures dereference @long-calculation ◆ blocks if value is not available yet ◆ returns saved value on subsequent calls ■ dereference with timeout (deref (future (Thread/sleep 5000) :done!) 1000 :impatient!) ;= :impatient!

4 / 15 Future (example)

( defn get−document [id] ; ... do some work to retrieve the identified ; document’s metadata ... {:url "http://www. mozilla .org/about/manifesto.en.html" : title "The␣Mozilla␣Manifesto" :mime "text/html" :content ( future (slurp "http://www. mozilla .org/about/manifesto.en.html"))}) ■ slurp fetches the document from the web ■ content is retreived once, starting immediately ◆ several threads requesting it wait for the same value ■ delay instead of future: starts only at first request

5 / 15 Future (mechanics)

Overview ■ executed in the thread from the agents’ unlimited thread Clojure Future pool Future (example) Future ◆ may use IO (mechanics) Promises ■ Thread vs future Javascript/JQuery Scala/Akka ◆ futures cheaper than using thread directly ◆ more concise ◆ implements java.util.concurrent.Future

6 / 15 Promises

Overview ■ delays and futures are bound to the result of a code Clojure Future block Future (example) ■ promise is not bound to any code block Future (mechanics) (def p (promise)) Promises

Javascript/JQuery (realized? p) ;= false Scala/Akka futures (deliver p 42) ;= # (realized? p) ;= true @p ;= 42 ■ deliver assigns value to the promise ■ deref blocks until assigned, supports timeout too ■ similar to a one-time, single-value pipe ◆ sometimes called dataflow variables and are the building blocks of declarative concurrency (Oz)

7 / 15 Overview

Clojure

Javascript/JQuery Introduction Future event as object Making promises Deferred vs promise Pipes Pipe cascading Javascript/JQuery Scala/Akka futures

8 / 15 Introduction

Overview ■ JQuery 1.4 and earlier Clojure

Javascript/JQuery Introduction $.get(’/mydata’, { Future event as object success: onSuccess, Making promises failure: onFailure, Deferred vs promise always: onAlways Pipes }); Pipe cascading Scala/Akka futures ■ With JQuery 1.5 ajax functions you know ($.ajax, $.get, and $.post) now return Promises

var promise = $.get(’/mydata’); promise.done(onSuccess); promise.fail(onFailure); promise.always(onAlways);

■ why this is better? 9 / 15 Future event as object

Overview ■ All actions do not have to be defined on creation Clojure Javascript/JQuery ◆ Promise can be passed around Introduction Future event as ◆ effects (triggering animations, inserting HTML, object Making promises locking/unlocking user input, and so on) added Deferred vs incrementally (stacked) promise Pipes ■ the order of handlers is preserved Pipe cascading Scala/Akka futures ■ Combine promises ◆ in parallel, .g. wait for 2 events (animation completion and ajax request result) ◆ pipeline, specify subsequent reactions to the future async results ■ resulting promise is the result of the final task in the series

10 / 15 Making promises

■ Either always+done or always+fail will be called var promptDeferred = new $.Deferred(); promptDeferred.always(function(){ console.log(’A choice was made:’); }); promptDeferred.done(function(){ console.log(’Starting game...’); }); promptDeferred.fail(function(){ console.log(’No game today.’); }); ■ triggering manually with resolve or reject $(’#playGame’).focus().on(’keypress’, function(e) { var Y = 121, N = 110; if (e.keyCode === Y) { promptDeferred.resolve(); } else if (e.keyCode === N) { promptDeferred.reject(); } else { return false; // our Deferred remains pending }; }); 11 / 15 Deferred vs promise

Overview ■ Promise in JQuery is read-only view of a deferred Clojure

Javascript/JQuery var promise1 = promptDeferred.promise(); Introduction var promise2 = promptDeferred.promise(); Future event as object console.log(promise1 === promise2); // true Making promises Deferred vs ■ In fact promise method returns self for promises promise Pipes console.log(promise1 === promise1.promise()); Pipe cascading // true Scala/Akka futures ■ convenient for protecting the deferred from external writes

12 / 15 Pipes

Overview ■ you can’t attach handlers to the second task until the Clojure first one is complete Javascript/JQuery Introduction var getPromise = $.get(’/query’); Future event as object getPromise.done(function(data) { Making promises var postPromise = $.post(’/search’, data); Deferred vs promise }); Pipes // Now we’d like to attach handlers to postPromise Pipe cascading // see the problem: it is in internal scope Scala/Akka futures ■ first promise result is handled by the code, that should return second promise var getPromise = $.get(’/query’); var postPromise = getPromise.pipe(function(data) return $.post(’/search’, data); }); Effectively, pipe is a window into the future! ◆ if return simple value then it is final promise result

13 / 15 Pipe cascading

Overview ■ pipe doesn’t require you to provide every possible Clojure callback: Javascript/JQuery ■ Introduction you’ll usually just want to write Future event as object var p = originalPromise.pipe(successCallback); Making promises Deferred vs promise or the following: Pipes Pipe cascading var p = originalPromise.pipe(null, failCallback); Scala/Akka futures ■ cascading: a failure is propagated to the last promise automatically var step1 = $.post(’/step1’, data1); var step2 = step1.pipe(function() { return $.post(’/step2’, data2); }); var lastStep = step2.pipe(function() { return $.post(’/step3’, data3); });

14 / 15 Overview

Clojure

Javascript/JQuery

Scala/Akka futures

Scala/Akka futures

15 / 15