Slide 1

Slide 1 text

Functional Reactive Programming FP, Javascript y extra de bacon

Slide 2

Slide 2 text

Javier Onielfa Belenguer Software Engineer @ R&D Astellia Spain @onielfadev

Slide 3

Slide 3 text

Summary 1. Functional Programming 2. Theory a. Classical FRP b. Transformations 3. Coding a. Architecture b. Examples 4. Implementations and problems a. Advantages/Disavantages b. Implementation 5. References

Slide 4

Slide 4 text

Functional Programming?

Slide 5

Slide 5 text

FP Crash Course

Slide 6

Slide 6 text

Functional Programming ● Functional programming is programming with functions ● Functions are first class citizens: You can pass them, return them and store them in datastructures. ● Functions tend to be pure. The evaluation of a function ONLY depends on its inputs. ● Equational reasoning. ● Embraces a data-oriented view. You are transforming data.

Slide 7

Slide 7 text

Let’s begin

Slide 8

Slide 8 text

Programming viewed as transforming data INPUT COMPUTER PROGRAM DATA DATA OUTPUT

Slide 9

Slide 9 text

Examples INPUT WEB SERVER PROCESS HTTP REQ HTTP RES OUTPUT INPUT ALGORITHM PROCESS PROBLEM SOLUTION OUTPUT INPUT WEB APP PROCESS UI EVENT HTML REDRAW OUTPUT

Slide 10

Slide 10 text

Real world apps don’t receive only one piece of data. What’s missing?

Slide 11

Slide 11 text

Real world apps don’t receive only one piece of data. What’s missing? TIME

Slide 12

Slide 12 text

Facing values that change over time app.post('/process-file', function(req, res) { var inputFile = 'input.txt'; var outputFile = 'output.txt'; fs.readFile(inputFile, function(err, data) { if (err) return res.status(500).send(err); process1(data, function(err, data) { if (err) return res.status(500).send(err); process2(data, function(err, data) { if (err) return res.status(500).send(err); process3(data, function(err, data) { if (err) return res.status(500).send(err); fs.writeFile(outputFile, data, function(err) { if (err) return res.status(500).send(err); res.status(200).send('processed successfully using callback hell'); }); }); }); }); }); });

Slide 13

Slide 13 text

Classic FRP As semantically defined in Functional Reactive Animation, Conal Elliot et al, 1998. Behavior ● It’s a function of time ○ type Behavior :: T -> a ● Continuous time-varying values. ● Sample rate independent. ● Introduced for modelling animation/physics (velocity, gravity,etc) ● Inefficient implementation. Led to space leaks.

Slide 14

Slide 14 text

Classic FRP As semantically defined in Functional Reactive Animation, Conal Elliot et al, 1998. EventSource ● Stream of timed values. ○ type EventSource :: [(T,a)] where Tn < Tn+1 ● Discrete time values. ● It’s like you are in another dimension where you can see the past, present and future. The whole timeline. ● Fits perfectly for heavily event oriented applications.

Slide 15

Slide 15 text

“There is no future. There is no past… Time is simultaneous, an intricately structured jewel that humans insist on viewing one edge at a time, when the whole design is visible in every facet.” Dr. Manhattan, Watchmen

Slide 16

Slide 16 text

C 1s Keystrokes O 3s D E 7s M 9s O 12s 4s Keystrokes = [(1,’C’),(3,’O’),(4,’D’),(7,’E’),(9,’M’),(12,’O’), (14,’T’),(17,’I’)] I 17s T 14s Event Source

Slide 17

Slide 17 text

Wait!

Slide 18

Slide 18 text

Semantically, EventStream is a list, what if I use...

Slide 19

Slide 19 text

C 1s Ks O 3s D E 7s M 9s O 12s 4s Map f(v) = toLowerCase(v) c 1s Ks.map(f) o 3s d e 7s m 9s o 12s 4s 14s t 14s T

Slide 20

Slide 20 text

C 1s Ks O 3s D E 7s M 9s O 12s 4s Filter f(v) = return v == ‘o’; ks.filter(f) o 3s o 12s 14s T

Slide 21

Slide 21 text

Es1 1 3s 2 12s Merge 14s 3 Es2 B C 7s D 9s 4s A 1s Es1.merge(Es2) 1 3s B C 7s D 9s 2 12s 4s 14s 3 A 1s

Slide 22

Slide 22 text

1 1s c 1 3s 1 1 7s 1 9s 1 12s 4s Scan plus(a,b) = return a+b; c.scan(0,plus) 14s 1 1 1s 2 3s 3 4 7s 5 9s 6 12s 4s 14s 7

Slide 23

Slide 23 text

LET’S CODE!

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

How do I create an EventStream? ● From jQuery/Zepto object: ○ $(‘#mydiv’).asEventStream(‘click’) ● From promise object: ○ Bacon.fromPromise($.ajax(“/search/”+query”)) ● From DOM event: ○ Bacon.fromEvent(document.body, ‘click’) ● One-event eventstream: ○ Bacon.once(‘Hello’) ● Interval: ○ Bacon.interval(1000, ‘Tick’)

Slide 26

Slide 26 text

Architecture of an FRP app Event Stream ... Event Stream Event Stream Merge Model Transformation Side Effects ... Side Effects Side Effects

Slide 27

Slide 27 text

Simple Up/Down example

Slide 28

Slide 28 text

Simple Up/Down example Up Click Stream Down Click Stream Transform Merge Div Content Transform

Slide 29

Slide 29 text

Simple Up/Down example var up = $('#upButton').asEventStream('click'); var down = $('#downButton').asEventStream('click'); var counter = up .map(1) .merge(down.map(-1)) .scan(0, (acc, val) => return acc + val;); counter.assign($('#result'), 'text');

Slide 30

Slide 30 text

Form validation example

Slide 31

Slide 31 text

Name Keyup Stream Min Keyup Stream Merge to Model Filter Valid Form validation example Max Keyup Stream Enable Submit Show error msg

Slide 32

Slide 32 text

Form validation example // Input streams var nameStream = $('#name') .asEventStream('keyup') .map(event => return event.target.value;) .skipDuplicates() .toProperty($('#name').val()); var minStream = $('#min') .asEventStream('keyup') .map(event => return parseInt(event.target.value);) .skipDuplicates() .toProperty(parseInt($('#min').val()));

Slide 33

Slide 33 text

Form validation example // Model Stream var modelStream = Bacon.combineTemplate({ name: nameStream, min: minStream, max: maxStream });

Slide 34

Slide 34 text

Form validation example //Side effects evaluateStream.map(m => return !m.valid;) .assign($('#submitButton'), 'attr', 'disabled'); evaluateStream.map(m => return m.message;) .assign($('#error'), 'text');

Slide 35

Slide 35 text

Shape designer example

Slide 36

Slide 36 text

Shape Stream Color Stream Merge to Model Transform Shape designer example Size Stream Canvas Drawing

Slide 37

Slide 37 text

Shape designer example // Input streams var colorStream = $('#color').asEventStream('change') .map(event => return event.target.value;) .skipDuplicates() .toProperty($('#color').val()) .map(c => transformColor(c));

Slide 38

Slide 38 text

Shape designer example //ModelStream var modelStream = Bacon.combineTemplate({ shape: shapeStream, size: sizeStream, color: colorStream });

Slide 39

Slide 39 text

Shape designer example // SideEffects var canvas = document.getElementById("canvas"); var ctx = canvas.getContext('2d'); modelStream.onValue(m => { drawModel(ctx, m); });

Slide 40

Slide 40 text

Twitter Map example

Slide 41

Slide 41 text

Tweet Stream Twitter Map example (Server) WS Connection Stream Socket Send

Slide 42

Slide 42 text

function randomTweet(v){ return { pos: { lat: getRandomArbitrary(38.46975,40.46975), lng: getRandomArbitrary(-0.7,1.37739), }, text: 'Hola' }; } Twitter Map example (Server)

Slide 43

Slide 43 text

io.on('connection', socket => { bacon.interval(1000, {}) .map(randomTweet) .onValue(t => socket.emit('tweet', t)); }); Twitter Map example (Server)

Slide 44

Slide 44 text

Tweet Stream North Filter Transform Twitter Map example (Client) Merge South Filter Transform Put Marker Write Tweet

Slide 45

Slide 45 text

var tweetStream = Bacon.fromEvent(socket, 'tweet'); var northStream = tweetStream.filter(inNorth) .map(t => return t.text + ' (N)';); var southStream = tweetStream.filter(inSouth) .map(t => return t.text + ' (S)';); var finalStream = northStream.merge(southStream); finalStream.onValue(t => { putMarker(t); writeTweet(t); }); Twitter Map example (Client)

Slide 46

Slide 46 text

Conclusion

Slide 47

Slide 47 text

Advantages ● It allows you to define time-dependent application in a declarative way. ● Time-varying values are first class citizen. ● It allows you to use a data transformation style using mostly pure functions. ● Side-effects are confined to one part of the application

Slide 48

Slide 48 text

Problems ● What if one transformation function consumes too much time? ● What if one EventStream is too fast for the system to process? ● What if one EventStream in a zip is way faster than the other one?

Slide 49

Slide 49 text

Implementation ● Pull-based ○ Demand-driven. Sampling of the reactive EventStreams. ● Push-based ○ It can be implemented on top of event loops. ● Infinite vs finite ○ (Bacon.js) Streams are finite: They can start and end at arbitrary moments. ○ (Elm) Streams are infinite: Stream are always “producing” values (Hot/Cold).

Slide 50

Slide 50 text

Libraries ● JS : Bacon.js, RxJs, “Elm” ● Java: RxJava ● C#: Rx.Net ● Objective-C: ReactiveCocoa ● Ruby: Frapuccino ● Python: RxPy

Slide 51

Slide 51 text

References, Links and Videos ● Functional Reactive Animation, Conal Elliot et al, 1998 ● Push-Pull Functional Reactive Programming, Conal Elliot ● Deprecating the observer pattern, Martin Odersky et al ● React 2014: Erik Meijer - What does it mean to be Reactive? ● “Controlling Time and Space: understanding the many formulations of FRP” by Evan Czaplicki (Elm creator) ● Ryan Trinkle - Reflex: Practical Functional Reactive Programming (Haskell) ● Lambda Jam 2014 - Conal Elliot - The Essence and Origins of Functional Reactive Programming

Slide 52

Slide 52 text

Thanks!

Slide 53

Slide 53 text

Questions?