Introduction to functional reactive programming

with RxJS

23.03.2017 - Graffiti HUB

Chi sono

Giulio Collesei

Front end dev @AQuest

 

Motivazioni

Introduction to functional reactive programming

with RxJS

Functional programming

Cosa significa?

Functional programming

Functional programming

Scrivere applicazioni utilizzando funzioni

f Main()

f A()

f B()

f A1()

f A2()

f A3()

f A4()

Functional programming

È tutto?

Functional programming

nope!

Functional programming

Functional programming

  • Functions are first class entities

  • Functions are pure

  • Functions use immutable data

  • Functions guarantee referential transparency

 

Functional programming

  • Functions are first class entities

Functional programming

  • Functions are first class entities

 

// Function declaration
function sayHello(name) {
    return `Hello, ${name}`
}

// Function expression
const sayHello = name => `Hello, ${name}`

Functional programming

const putInPot = i1 => console.log(`${i1} in pot!`);
const cook = (i1, i2, f) => {
    console.log(`Cooking ${i1} and ${i2}`);
    f(i1);
    f(i2);
};

cook('chicken', 'potatoes', putInPot);

// -> Cooking chicken and potatoes
// -> chicken in pot!
// -> potatoes in pot!
  • Functions are first class entities

 

Functional programming

const getSecret = (secret) =>
    () => console.log(secret);

const mySecret = getSecret('my secret');

mySecret();

// -> my secret
  • Functions are first class entities

 

Functional programming

  • Functions are pure

Functional programming

  • Functions are pure

 

  1. Il risultato della funzione dipende solo dagli input della stessa
     
  2. La funzione non altera né ciò che sta fuori né i parametri ad esse passati.

Functional programming

  • Functions are pure

 

const PI = 3.14;

// Non-pure function
const calculateArea = (radius) =>
    radius * radius * PI;

// Pure function
const calculateArea = (radius, PI) =>
    radius * radius * PI;

Functional programming

  • Functions use immutable data

Functional programming

  • Functions use immutable data

 

Nella programmazione funzionale non c'è più il concetto di variabile. I dati non cambiano nel tempo.

Functional programming

  • Functions use immutable data

 

// Non-immutable data
let myString = 'Hello';
myString = myString.concat(' world!');

// Immutable data
const myString = 'Hello';
const myString2 = myString.concat(' world!');

Functional programming

  • Functions guarantee referential transparency

 

Functional programming

  • Functions guarantee referential transparency

 

f(x) = x * x

Functional programming

  • Functions guarantee referential transparency

 

f(x) = x * x
f(4) = 16

Functional programming

  • Functions guarantee referential transparency

 

f(x) = x * x
f(4) = 16
f(4) = 16
f(4) = 16

Functional programming

  • Functions guarantee referential transparency

 

f(x) = x * x
g(x) = f(x) + x

Functional programming

  • Functions guarantee referential transparency

 

f(x) = x * x
g(x) = f(x) + x
g(4) = f(4) + 4

Functional programming

  • Functions guarantee referential transparency

 

f(x) = x * x
g(x) = f(x) + x
g(4) = f(4) + 4
g(4) = 16 + 4

Functional programming

  • Functions guarantee referential transparency

 

La referential transparency ci da la possibilità di cambiare un espressione con il suo risultato senza compromettere il funzionamento dell'applicazione.

   Pure function

+ Immutable data

= Referential transparancy

Functional programming

Benefits

Functional programming

  • Più facili da capire
  • Più facili da riutilizzare
  • Più facili da testare
  • Più facili da ottimizzare e mantenere

 

Benefits

Nella programmazione funzionale le funzioni sono:

Functional programming

Imperative

vs

Declarative

Functional programming

const a = [1,2,3,4,5];

// Imperative (how)
let b = 0;

for (let i = 0; i < a.length; i++) {
    b = b + a[i];
}

// Declarative (what)
const sum = (b, a) => b + a;
const b = a.reduce(sum, 0);

Functional programming

Patterns

Functional programming

higher-order function

Functional programming

Higher-order function

 

Funzioni che accettano come parametro altre funzioni e/o restituisco nuove funzioni

Array.prototype
.filter()
.map()
.reduce()
.reduceRight()
.find()
.every()
.concat()

Functional programming

function composition

Functional programming

Composizione di funzioni

 

È l'applicazione di una funzione al risultato di un'altra

A
B
B
C
C
D
D

Res.

func1()
func2()
func3()

Functional programming

Composizione di funzioni

 

È l'applicazione di una funzione al risultato di un'altra

f ∘ g        (f dopo g)

Functional programming

Composizione di funzioni

 

È l'applicazione di una funzione al risultato di un'altra

f ∘ g        (f dopo g)
(f ∘ g)(x)

Functional programming

Composizione di funzioni

 

È l'applicazione di una funzione al risultato di un'altra

f ∘ g        (f dopo g)
(f ∘ g)(x)
f(g(x)) = y

Functional programming

Composizione di funzioni

 

È l'applicazione di una funzione al risultato di un'altra

// two functions that we'll compose
const applyTax = x => x * 1.08;
const applyShipping = x => x + 10;

const totalCost = compose(applyShipping, applyTax);

Functional programming

Partial application

Functional programming

Applicazione parziale di funzione

 

L'applicazione di una funzione a una parte dei suoi argomenti

f(a, b) = c

Functional programming

Applicazione parziale di funzione

 

L'applicazione di una funzione a una parte dei suoi argomenti

f(a, b) = c
(f1(a))(b)

Functional programming

Applicazione parziale di funzione

 

L'applicazione di una funzione a una parte dei suoi argomenti

f(a, b) = c
(f1(a))(b) = f(a, b) = c

Functional programming

// Partial application
const f = (a, b, c) => a * b * c;
const g = partialApplication(f, [2, 3]);

// ...

const h = g(4); // 24

enough with functional!

Reactive programming

Cosa significa?

Reactive programming

Reactive programming

È un paradigma di programmazione che mira alla gestione di flussi di dati asincroni (stream) basati su eventi.

Reactive programming

Stream?

Reactive programming

Gli stream sono simili agli array, solo asincroni.

Array

[1, 2, 3]

 

Stram

[1, ..... 2, ...... 3]

Reactive programming

Una serie di eventi ordinati nel tempo

Reactive programming

Una serie di eventi ordinati nel tempo

Tempo

e
e
e

Reactive programming

A cosa serve RP?

Reactive programming

a = b + c

Reactive programming

Listener

(memory leaks)

Callback

(callback hell)

Promises

(cannot be cancelled)

Reactive programming

Observable

Reactive programming

Come funziona?

Reactive programming

 Come manipolare i dati?

Reactive programming

Tempo

// tieni i pari

1

2

3

4

Reactive programming

Tempo

filter() // tieni i pari

1

2

3

4

2

4

// fai il quadrato

Reactive programming

Tempo

filter() // tieni i pari

1

2

3

4

2

4

map() // fai il quadrato

4

16

// riduci con somma

Reactive programming

Tempo

filter() // tieni i pari

1

2

3

4

2

4

map() // fai il quadrato

4

16

reduce() // riduci con somma

4

20

Reactive programming

Merge

Reactive programming

KeyPress

KeyPress
+

Mouse move

merge()

Mouse move

Reactive programming

Reactive programming

Concat

Reactive programming

Reactive programming

Switch

(Higher-order event stream)

Reactive programming

Reactive programming

RxJS

RxJS

RxJS

An API for asynchronous programming
with observable streams

RxJS

http://reactivex.io/languages.html 

  • Java: RxJava
  • JavaScript: RxJS
  • C#: Rx.NET
  • Scala: RxScala
  • C++: RxCpp
  • Ruby: Rx.rb
  • Python: RxPY
  • ......

RxJS

Terminologia

RxJS

Observable

RxJS

Observable

 

È il wrapper dello stream.

Un Observable ha 3 eventi:

- Next

- Error

- Complete

RxJS

var source = Rx.Observable.range(0, 3);

Observable

RxJS

Observables are lazy-evaluated

RxJS

Observer (Subscriber)

RxJS

Observer

 

L'oggetto passato al metodo .subscribe() che contiente le 3 callback

RxJS

var source = Rx.Observable.range(0, 3);

source.subscribe({
  next: x => console.log(`Next: ${x}`),
  error: err => console.error(`Error: ${err}`),
  complete: () => console.log(`Done!`)
});

Observable

Observer

RxJS

Operators

RxJS

Operators

 

Sono le funzioni che ci permettono di manipolare gli observables.

 

Operators = RxJs

RxJS

Creare un observable

RxJS

// da qualsiasi valore
Rx.Observable.of(0, 3, 'fevr', ['a', 'b']);

RxJS

// da qualsiasi valore
Rx.Observable.of(0, 3, 'fevr', ['a', 'b']);
// da un array o da una promise
Rx.Observable.from([1, 2, 3]);

RxJS

// da qualsiasi valore
Rx.Observable.of(0, 3, 'fevr', ['a', 'b']);
// da un array o da una promise
Rx.Observable.from([1, 2, 3]);
// da un evento
Rx.Observable.fromEvent(myBtn, 'click');

RxJS

// da qualsiasi valore
Rx.Observable.of(0, 3, 'fevr', ['a', 'b']);
// da un array o da una promise
Rx.Observable.from([1, 2, 3]);
// da un evento
Rx.Observable.fromEvent(myBtn, 'click');
// da un intervallo (tipo setTimeout)
Rx.Observable.interval(1000);

RxJS

// da un array o da una promise
Rx.Observable.from([1, 2, 3]);
// da un evento
Rx.Observable.fromEvent(myBtn, 'click');
// da un intervallo (tipo setTimeout)
Rx.Observable.interval(1000);
// da un timer (delay, interval)
Rx.Observable.timer(100, 1000);
// da qualsiasi valore
Rx.Observable.of(0, 3, 'fevr', ['a', 'b']);

RxJS

// da un range
Rx.Observable.range(30, 10);

RxJS

// da un range
Rx.Observable.range(30, 10);
// da una funzione con bindCallback
const fetch = (url, callback) => {
    //...

         callback('data')

}

const rxFetch = Rx.Observable.bindCallback(fetch);

RxJS

// da un range
Rx.Observable.range(30, 10);
// da una funzione con bindCallback
const fetch = (url, callback) => {
    //...

         callback('data')

}

const rxFetch = Rx.Observable.bindCallback(fetch);

// never
Rx.Observable.never();

RxJS

Merge observable

RxJS

const mouseMove$ = Rx.Observable.fromEvent(document, 'mousemove');
const click$ = Rx.Observable.fromEvent(document, 'click');

const uiEvents$ = Rx.Observable.merge(mouseMove$, click$)
    .subscribe(e => console.log(e.type));


// click
// mousemove
// mousemove
// mousemove
// click
// mousemove
// mousemove
// mousemove
// mousemove

RxJS

Concat observable

RxJS

const interval100$ = Rx.Observable.interval(100)
    .take(5);

const interval2000$ = Rx.Observable.interval(2000);

const intervalConcat$ = Rx.Observable.concat(interval100$, interval2000$)
    .subscribe(console.log);


// 0
// 1
// 2
// 3
// 4
// 0
// 1
// 2
// 3
// ...

RxJS

combineLatest

RxJS

const interval100$ = Rx.Observable.interval(100);
const interval2000$ = Rx.Observable.interval(2000);

const intervalConcat$ = Rx.Observable.combineLatest(interval100$, interval2000$)
    .subscribe(console.log);

// [19, 0]
// [20, 0]
// [21, 0]
// ...
// [39, 1]
// ...
// [39, 1]
// ...
// [59, 2]

RxJS

Demo!

RxJS

http://codepen.io/giuliocollesei/pen/vxjyjp/

Drag and drop

RxJS

Redux

http://codepen.io/giuliocollesei/pen/ryvjKG

RxJS

Risorse utili

RxJS

Documentazione ufficiale:

http://reactivex.io/rxjs/

 

Introduzione FRP by André Staltz

https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

 

Video corsi su egghead.io

https://egghead.io/technologies/rx

 

RxMarbles (stream interattivi)

http://rxmarbles.com/

RxJS

Fine

Made with Slides.com