|
1 | 1 | <!-- .slide: data-background="#003d73" -->
|
2 |
| -## Functional error handling |
| 2 | + |
| 3 | +## Reactive programing |
3 | 4 |
|
4 | 5 |  <!-- .element style="width: 200px; position: fixed; bottom: 50px; left: 50px" -->
|
5 | 6 |
|
6 | 7 | ---
|
7 | 8 |
|
8 |
| -```csharp |
9 | 9 |
|
10 |
| -public interface IDisposable { |
11 |
| - public void Dispose(); |
12 |
| -} |
| 10 | +### Reactive programing |
| 11 | + |
| 12 | +* Declarative paradigm |
| 13 | + * responding to events |
| 14 | +* Imparative vs declarative |
| 15 | + |
| 16 | +```[1-3|4-8] |
| 17 | +// Imparative |
| 18 | +let a = b + c |
| 19 | +// a is assigned and never changed |
| 20 | +// Reactive |
| 21 | +let a' = b + c |
| 22 | +b <- 'new_value' |
| 23 | +// a is now recombuted |
| 24 | +``` |
| 25 | +<!-- .element: class="fragment" --> |
| 26 | + |
| 27 | +---- |
| 28 | + |
| 29 | +### Reactive programing |
| 30 | + |
| 31 | +* ReactiveX |
| 32 | + * RXjs (used in Angular, ..) |
| 33 | + * Rx.NET |
| 34 | + * RxJava |
| 35 | + * ... |
| 36 | + |
| 37 | +---- |
| 38 | + |
| 39 | +### When to use |
| 40 | + |
| 41 | +* Emitting and consuming events are async<br/><!-- .element: class="fragment" --> |
| 42 | +* Events are async<br/><!-- .element: class="fragment" --> |
| 43 | +* Events vs Reactive programing<br/><!-- .element: class="fragment" --> |
| 44 | + * robustness |
| 45 | + * extend |
| 46 | +* Learing curve<br/><!-- .element: class="fragment" --> |
| 47 | + |
| 48 | +--- |
| 49 | + |
| 50 | +### Creating events |
| 51 | + |
| 52 | +```fsharp [1-11|12-15] |
| 53 | +let createTimer timerInterval eventHandler = |
| 54 | + let timer = new System.Timers.Timer(float timerInterval) |
| 55 | + timer.AutoReset <- true |
| 56 | +
|
| 57 | + timer.Elapsed.Add eventHandler |
13 | 58 |
|
14 |
| -using(var db = new SQLConnection("sadf")) { |
15 |
| - db.Query("dsaf"); |
| 59 | + async { |
| 60 | + timer.Start() |
| 61 | + do! Async.Sleep 5000 |
| 62 | + timer.Stop() |
| 63 | + } |
| 64 | +// call createTimer |
| 65 | +let basicHandler _ = printfn "tick1 %A" DateTime.Now |
| 66 | +let basicTimer1 = createTimer 1000 basicHandler |
| 67 | +Async.RunSynchronously basicTimer1 |
| 68 | +``` |
16 | 69 |
|
17 |
| - ... |
18 |
| -} |
| 70 | +---- |
| 71 | + |
| 72 | +### Using the built in Observable |
| 73 | + |
| 74 | +```fsharp [1-13|14-21] |
| 75 | +let createTimerAndObservable timerInterval = |
| 76 | + let timer = new System.Timers.Timer(float timerInterval) |
| 77 | + timer.AutoReset <- true |
| 78 | +
|
| 79 | + let observable = timer.Elapsed |
| 80 | +
|
| 81 | + let task = async { |
| 82 | + timer.Start() |
| 83 | + do! Async.Sleep 5000 |
| 84 | + timer.Stop() |
| 85 | + } |
| 86 | +
|
| 87 | + (task,observable) |
| 88 | +// Calling from somewhere else |
| 89 | +let basicTimer2, timerEventStream = |
| 90 | + createTimerAndObservable 1000 |
| 91 | +timerEventStream |
| 92 | +|> Observable.subscribe //basicHandler |
| 93 | + (fun _ -> printfn "tick2 %A" DateTime.Now) |
| 94 | +|> ignore // disposable not disposed |
| 95 | +Async.RunSynchronously basicTimer2 |
| 96 | +``` |
| 97 | + |
| 98 | +---- |
| 99 | + |
| 100 | +### Piping events |
| 101 | + |
| 102 | +```fsharp |
| 103 | +let timerCount2, timerEventStream = createTimerAndObservable 500 |
| 104 | +timerEventStream |
| 105 | +|> Observable.scan (fun count _ -> count + 1) 0 |
| 106 | +|> Observable.subscribe (fun count -> printfn "1 timer ticked with count %i" count) |
| 107 | +|> ignore // disposable not disposed |
| 108 | +``` |
| 109 | + |
| 110 | +---- |
| 111 | + |
| 112 | +### Merging events |
| 113 | + |
| 114 | + |
| 115 | + |
| 116 | +--- |
19 | 117 |
|
| 118 | +### References |
20 | 119 |
|
21 |
| -``` |
| 120 | +* [Observable](https://fsharp.github.io/fsharp-core-docs/reference/fsharp-control-observablemodule.html) |
| 121 | +* [F# For fun and profits](https://fsharpforfunandprofit.com/posts/concurrency-reactive/) |
0 commit comments