25 Agosto 2015
Future e Promise in Scala

Primo articolo su Scala: “Future e Promise”

Scala è un linguaggio funzionale ad oggetti che  permette di scrivere codice in maniera molto concisa, pulita e davvero intuitiva.

Questo è il primo dei post su Scala e parla principalmente di due costrutti piuttosto simili, future e promise, fondamentali per la programmazione concorrente.

Future

Un future è un costrutto usato per recuperare il risultato di un’operazione concorrente e che quindi potrebbe non essere ancora disponibile quando si cerca di accedervi; in pratica è una sorta di “placeholder”/segnaposto, creato per  un valore(solitamente il risultato di una computazione) che potrebbe diventare disponibile. A questo risultato ci si può accedere in maniera sincrona, e quindi bloccante (da evitare il più possibile), o asincrona e quindi non bloccante.

Si dice completato(“completed”) se ha prodotto un risultato che sia un valore o un’eccezione, altrimenti si dice non completato(“not completed”);  se è completato con un valore il future è completato con successo(“successfully completed”), se invece è completato con un’eccezione generata dalla computazione allora si dice fallito(“failed”)

Un future può essere assegnato una volta sola, dal momento in cui gli viene assegnato un valore o un’eccezione, diventa di fatto immutabile e non potrà essere sovrascritto.

Per creare un future possiamo utilizzare il metodo apply del “companion-object” che richiede due argomenti come input: body (il codice da eseguire nel future) e l’ ExecutionContext che è implicito.

Execution Context

L’ ExecutionContext è il Thread-Pool dove sarà eseguito il processo; possiamo usare quello globale importando scala.concurrent.ExecutionContext.Implicits.global oppure usarne uno specifico. Un ExecutionContext “ad hoc” è consigliato nel caso si debba eseguire del codice che richiede lunghi tempi di computazione o nel caso operazioni di IO bloccanti.

Accedere al risultato

Callback (asincrona)

Nell’esempio ci siamo registrati alla callback utilizzando il metodo onComplete

che riceve in ingresso una funzione del tipo Try[T] => U . La callback viene applicata ad un valore di tipo Success[T] se il future si completa con successo, altrimenti ad un valore di tipo Failure[T].

Composizione di future

Supponiamo di dover applicare una funzione al risultato di più future in cascata.

tratto dalla documentazione Scala

Nell’esempio precedente si è creato il future rateQuote che restituisce il tasso di conversione corrente. Quando il server ha restituito il  tasso di conversione in dollari e il future si è completato con successo, applicando la callback si è recuperato il valore e si è applicata la logica per decidere se acquistare o meno utilizzando ancora una volta un future. A questo si è riapplicata di nuovo una callback per scrivere a monitor se è stato fatto l’acquisto.

..si può fare, ma non è proprio bello e comodo, ci sono però i combinators come map, flatMap, filter ecc che ci permettono riscrivere l’esempio precedente in maniera molto più elegante.

recover / recoverWith / fallbackTo

Tra gli altri combinators, particolare attenzione per recover, recoverWith e fallbackTo

def recover[U >: T](pf: PartialFunction[Throwable, U])(implicit executor: ExecutionContext): Future[U]

Esempio:  
    future (6 / 0) recover { case e: ArithmeticException => 0 } // result: 0
    future (6 / 0) recover { case e: NotFoundException   => 0 } // result: exception
    future (6 / 2) recover { case e: ArithmeticException => 0 } // result: 3
  • recoverWith crea un nuovo future che gestisce ogni throwable del primo future che matcha(ArithmeticExpression nell’esempio); se non c’è match o il secondo future fallisce allora non farà nulla.
def recoverWith[U >: T](pf: PartialFunction[Throwable, Future[U]])(implicit executor: ExecutionContext): Future[U]

Esempio: 
    val primoFuture = future (6 / 0)
    val secondoFuture = future { Int.MaxValue }
    primoFuture recoverWith { case e: ArithmeticException => secondoFuture } // result: Int.MaxValue
  • recoverWith crea un nuovo future che gestisce ogni throwable del primo future che matcha(ArithmeticExpression nell’esempio), assegnandogli il valore di un altro future; se non c’è match o il secondo future fallisce allora non farà nulla.
def fallbackTo[U >: T](that: Future[U]): Future[U]

Esempio: 
    primoFuture.fallbackTo(secondoFuture)
  • fallbackTo restituisce un future con il valore di primoFuture se si completa con successo; se primoFuture fallisce restituisce un future con il valore di secondoFuture; se anche secondoFuture fallisce, fallbackTo restituirà un future con il throwable di primoFuture.

Projections

Abbiamo visto che si possono usare operazioni monadi, come map o flatMap, e come vengano applicate solo nel caso di successo del future; se invece volessimo utilizzare le stesse funzioni nel caso in cui qualcosa vada storto e venga sollevata un’eccezione, possiamo farlo chiamando il metodo failed del future che restituisce un Future[Throwable]

Blocking (sincrona)

Nonostante i future tendano, per loro natura, ad essere asincroni, per migliorare le performance e per evitare deadlock, a volte, è comunque necessario bloccare l’esecuzione del thread; per fare ciò, possiamo bloccare il future dall’esterno oppure possiamo fargli eseguire del codice che lo blocchi dall’interno.

Supponiamo di dover fare un’operazione IO bloccante, per esempio la read con un socket java

In questo esempio viene notificato al thread pool che il future contiene delle operazioni potenzialmente lunghe o bloccanti e il thread pool fa in modo di creare temporaneamente nuovi thread di lavoro(workers) per fare in modo che non tutti i thread siano bloccati.

Un’altro modo per bloccare l’esecuzione è usare l’oggetto Await; riprendiamo l’esempio usato per la composizione di future:

L’oggetto Await ci permette di assicurarci che purchase verrà eseguito dal thread chiamante obbligandolo ad aspettare che entrambi i future siano completati.

Il secondo parametro di result è il timeout; quando scade viene lanciata una TimeoutException.

Promise

A differenza del future, che è in sola lettura, la promise è un costrutto che permette di completare un future con un valore, usando il metodo success, o con un’eccezione, usando il metodo failure.

Ad ogni promise è associato un future a cui si può accedere chiamando il metodo future.

completando la promise con il success, abbiamo anche completato con successo il future associato e la promise non è più scrivibile. A questo punto viene anche chiamato l’ onSuccess/onComplete associato al future.

un esempio più completo:

Tag
Intré Camp – 30 Ottobre 2018

Racconto del camp aziendale svoltosi a Erba, castello di Casiglio.

Intré Camp – 26 Giugno 2018

Racconto del camp aziendale svoltosi all'agriturismo La Camilla

Agile Venture Prato 2018

Il racconto della giornata della prima edizione di un agile venture in quel di Prato.

A reactive programming example
Milan Kotlin Community Conf

The first Kotlin related Italian conference made from the community to the community!

Let's see how was it...

DroidCon IT, Turin, 19 & 20 April 2018: our report
Milan Kotlin Community Conference

How, why and what has lead us to the Milan Kotlin Community Conference.

Intré Camp – 13 Febbraio 2018

Racconto del camp aziendale svoltosi a Pontida, agriturimo Polisena

Vert.x – 4o articolo su Mokabyte!

4o articolo sul mondo Vert.x a cura di Marco

Vert.x – 3o articolo su Mokabyte!

3o articolo sul mondo Vert.x a cura di Marco

NoSlidesConf 2017

NoSlidesConf: una conferenza diversa dal solito

Vert.x – 2o articolo su Mokabyte!

2o articolo sul mondo Vert.x a cura di Marco

Vert.x – 1o articolo su Mokabyte!
IAD Urbino 2017 – Conferenza 18 Novembre

Racconto della conferenza presso l'università degli studi Carlo Bo di Urbino

IAD Urbino 2017 – Unconference 17 Novembre

#IAD17: Racconto della giornata di unconference presso l'Università degli Studi Carlo Bo di Urbino

Intré Camp – 5 Ottobre 2017

Racconto del camp aziendale svoltosi all'agriturismo La Camilla

Intré Camp – 18 Maggio 2017

Resoconto del camp aziendale svoltosi all'Oasi di Galbusera Bianca

CloudConf Torino 2017

CloudConf 2017 a Torino. Come è andata?

Mini IAD Vimercate 2017

Il racconto della giornata al Mini Italian Agile Day tenutasi a Vimercate.

Codemotion Milano 2016

Nel week-end del 25-26 novembre 2016 si è svolto il Codemotion Milano 2016.
Francesco Sacchi e Ferdinando Santacroce ci raccontano com'è andata.

Angular Conf 2016

Il racconto della nostra giornata alla Angular Conf 2016 a Torino, sia come spettatori e soprattutto come sponsor.

Intré Camp – 3 Novembre 2016

Un racconto di come è andata la nostra giornata di team building, tra sorrisi e battaglie ;)

Node.Js Italian conference – V edition

Cronistoria sulla nostra partecipazione alla 5^ edizione della Node.Js Italian Conference, con tante belle foto, stickers e...leggete :)

Business24 TV: Fabio Ghislandi presenta Intré

In questo breve intervista viene presentata Intré e il suo innovativo approccio allo sviluppo di software.

Come cambia il mondo dei linguaggi
WebRTC – #1 Video-Chat in javascript

Con la tecnologia WebRTC (Real Time Communication www.webrtc.org) è possibile integrare, all’interno di applicazioni che comprendono javascript, funzionalità di audio e video-chat, registrazione chat, condivisione schermo e signaling.

Future e Promise in Scala

Primo post sulla programmazione in Scala dedicato a future e promise, due costrutti fondamentali per la programmazione concorrente.

Come inviare dati live da un’applicazione C# Desktop al web usando le WebSocket

Questa è una guida passo passo su come esporre dati live da un'applicazione C# console ad un web browser usando le WebSocket. L'esempio è stato testato su Windows 7.

IOS Push notifications iOS 6 con Sencha Touch 2.2

Se state cercando di inviare una Push Notification al vostro iOS6 iPhone/iPad usando Sencha Touch 2.2 probabilmente avrete incontrato diversi problemi. In questo articolo vedremo passo passo come configurare i certificati, impostare il file Sencha package.json ed inviare una push notification con uno script PHP o C#.

Creare una issue in Jira con i sub-task predefiniti

E' possibile programmare script in Atlassian Jira usando Groovy. Questi script possono essere eseguiti allo scattare di un evento come alla creazione di una issue o al suo aggiornamento. Sfruttando questo principio vediamo come creare uno script che crea i sub-task in automatico alla creazione di una Issue.

Lego controllato con Cloudfoundy via WebSockets

Questo è un breve test di come è possibile controllare Lego Mindstorm con Cloudfoundry usando HTML5 e WebSockets.

Beaglebone how-to. Come cambiare lo stato di una pagina web premendo un pulsante con node.js

Questo articolo descrive come intercettare l'interrupt GPIO di una beagle bone e aggiornare, via web sockets, una pagina web usando node.js.

youSCADA presentato al Graphical Web 2012

Come controllare e monitorare i device usando una piattaforma Cloud? La soluzione è stata presentata al Graphical Web 2012 a Zurigo.

Chiamare una REST API con node.js

Node.js sta rivoluzionando il modo di programmare le piattaforme software. Basato sul Google V8 JavaScript Engine permette di scrivere codice lato server in JavaScript.

Top
Ogni nostro Sprint ha l'obiettivo di massimizzare il Valore per l'utente finale
Il tuo browser non è aggiornato!
Aggiornalo per vedere questo sito correttamente.Aggiorna ora

×