Slide 1

Slide 1 text

Alexander Voronov @aleks_voronov (Welcome!)

Slide 2

Slide 2 text

Reactive Cocoa http:/ /github.com/ReactiveCocoa/ReactiveCocoa

Slide 3

Slide 3 text

C# Reactive extensions (Rx) Clojure Elm Inspired By

Slide 4

Slide 4 text

Functional Reactive Programming (FRP) is a declarative programming paradigm for working with mutable time- varying values. FRP

Slide 5

Slide 5 text

Functional Reactive Programming (FRP) is a declarative programming paradigm for working with mutable time- varying values. Declarative – is about “what” not “how” to accomplish. Unlike imperative approach, system takes care of “how”. FRP

Slide 6

Slide 6 text

What and How What and how NSArray *words = ...; for (NSUInteger index = 0; index < words.count; index++) { NSString *word = words[index]; // do stuff }

Slide 7

Slide 7 text

What and How What and how NSArray *words = ...; for (NSUInteger index = 0; index < words.count; index++) { NSString *word = words[index]; // do stuff } What NSArray *words = ...; for (NSString *word in words) { // do stuff }

Slide 8

Slide 8 text

What and How What and how NSMutableArray *uppercasedWords = [NSMutableArray array]; for (NSString *word in words) { [uppercasedWords addObject:word.uppercaseString]; }

Slide 9

Slide 9 text

What and How What and how NSMutableArray *uppercasedWords = [NSMutableArray array]; for (NSString *word in words) { [uppercasedWords addObject:word.uppercaseString]; } What NSArray *uppercasedWords = [words map:^(NSString *word) { return word.uppercaseString; }];

Slide 10

Slide 10 text

Key concepts Avoids state and mutable data Any computation is mathematical function Functional Programming

Slide 11

Slide 11 text

State BOOL walksLikeADuck; // 2 states BOOL quacksLikeADuck; // 4 states BOOL isProbablyADuck; // 8 states BOOL maybeItCanFly; // 16 states Complexity is STATE

Slide 12

Slide 12 text

Minimize state by deriving it State BOOL walksLikeADuck; BOOL quacksLikeADuck; BOOL isProbablyADuck;

Slide 13

Slide 13 text

Minimize state by deriving it State BOOL walksLikeADuck; BOOL quacksLikeADuck; BOOL isProbablyADuck; BOOL walksLikeADuck; // 2 states BOOL quacksLikeADuck; // 4 states BOOL isProbablyADuck; // 4 states

Slide 14

Slide 14 text

Functions Comparison Imperative function has side effects that can change program state behaves differently depending on program state

Slide 15

Slide 15 text

Functions Comparison Imperative function has side effects that can change program state behaves differently depending on program state Mathematical function result of a function depends only on the arguments easier to understand and predict the behavior of a program

Slide 16

Slide 16 text

Reactive programming – programming paradigm oriented around data flows and the propagation of changes. Reactive Programming

Slide 17

Slide 17 text

Reactive programming – programming paradigm oriented around data flows and the propagation of changes. Reactive Programming Data flows can be either static or dynamic.

Slide 18

Slide 18 text

Data Changes Propagation Imperative approach b = 10 c = 11 a = b + c

Slide 19

Slide 19 text

Data Changes Propagation Imperative approach b = 10 c = 11 a = b + c (21)

Slide 20

Slide 20 text

Data Changes Propagation Imperative approach b = 10 c = 11 a = b + c (21) b = 11 a = ?

Slide 21

Slide 21 text

Data Changes Propagation Imperative approach b = 10 c = 11 a = b + c (21) b = 11 a = ? (21)

Slide 22

Slide 22 text

Data Changes Propagation Imperative approach b = 10 c = 11 a = b + c (21) b = 11 a = ? (21) Reactive approach b = 10 c = 11 a = b + c (21) b = 11 a = ? (22)

Slide 23

Slide 23 text

So What?

Slide 24

Slide 24 text

So What? Safer & easier multithreading

Slide 25

Slide 25 text

So What? Safer & easier multithreading Reusability

Slide 26

Slide 26 text

So What? Safer & easier multithreading Testability Reusability

Slide 27

Slide 27 text

So What? Safer & easier multithreading Testability Reusability Cleaner picture of data-flow

Slide 28

Slide 28 text

Why not KVO?

Slide 29

Slide 29 text

Why not KVO? Key Value Observing – mechanism that allows objects to be notified of changes to specified properties of other objects.

Slide 30

Slide 30 text

Why not KVO? Key Value Observing – mechanism that allows objects to be notified of changes to specified properties of other objects. not easy to use lots of unused parameters hard to maintain multithreading no block-based API

Slide 31

Slide 31 text

Why not KVO? // Some controller or else [dog addObserver:me forKeyPath:@"hunger" options:NSKeyValueObservingOptionNew context:NULL]; // . . . [dog removeObserver:me forKeyPath:@"hunger"]; // Observer class of ‘me’ object - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // . . . }

Slide 32

Slide 32 text

Why not KVO? // Some controller or else [dog addObserver:me forKeyPath:@"hunger" options:NSKeyValueObservingOptionNew context:NULL]; // . . . [dog removeObserver:me forKeyPath:@"hunger"]; // Observer class of ‘me’ object - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { // . . . } should remember pointer to observer object should remember key path should care of removing observer should implement observeValueForKeyPath... method in observer lots of if else statements because of keyPath

Slide 33

Slide 33 text

Why not KVO? Unlike KVO, in ReactiveCocoa and FRP in general you also can:

Slide 34

Slide 34 text

Why not KVO? Unlike KVO, in ReactiveCocoa and FRP in general you also can: combine operations together or derive state react on UI controls events and everything that changes over time operate with timers easily maintain networking operations operations can be chained sequently instead of nesting blocks

Slide 35

Slide 35 text

Bindings Developing for Mac OS X reveals Bindings. allow programming in IB replace boilerplate glue code

Slide 36

Slide 36 text

Bindings Developing for Mac OS X reveals Bindings. allow programming in IB replace boilerplate glue code This is real magic but . . . : no support for iOS development quite limited cannot be debugged

Slide 37

Slide 37 text

Basic Concepts Signals Events

Slide 38

Slide 38 text

Signals Signal – is a time varying value

Slide 39

Slide 39 text

Signals Signal – is a time varying value int a = 0 a = 1 a = 2 . . . a = n

Slide 40

Slide 40 text

Signals Signal – is a time varying value int a = 0 a = 1 a = 2 . . . a = n 1 2 n .

Slide 41

Slide 41 text

Events Signals send three different types of events to their subscribers:

Slide 42

Slide 42 text

Events Signals send three different types of events to their subscribers: next – provides a new value from the stream.

Slide 43

Slide 43 text

Events Signals send three different types of events to their subscribers: next – provides a new value from the stream. error – indicates that an error occurred before the signal could finish.

Slide 44

Slide 44 text

Events Signals send three different types of events to their subscribers: next – provides a new value from the stream. error – indicates that an error occurred before the signal could finish. completed – indicates that the signal finished successfully, and that no more values will be added to the stream.

Slide 45

Slide 45 text

ReactiveCocoa Basics Stream Sequence Signal

Slide 46

Slide 46 text

ReactiveCocoa Basics Stream Sequence Signal Stream (RACStream)– abstract representation of series of values. Streams are Haskell monads. Signal (RACSignal) – push-driven stream, represents data that will be delivered in the future. Sequence (RACSequence) – pull-driven stream that behaves more like a collection (NSArray, etc)

Slide 47

Slide 47 text

map filter flatten concat reduce fold merge combineLatest switchToLatest . . . ReactiveCocoa Toolset

Slide 48

Slide 48 text

Some practice

Slide 49

Slide 49 text

Subscribing to object changes [RACObserve(self, username) subscribeNext:^(NSString *newName){ NSLog(@"%@", newName); }];

Slide 50

Slide 50 text

Filtering object with value

Slide 51

Slide 51 text

[[RACObserve(self, username) filter:^(NSString *newName) { return [newName hasPrefix:@"a"]; }] subscribeNext:^(NSString *newName) { NSLog(@"%@", newName); }]; Filtering object with value

Slide 52

Slide 52 text

RAC(self.btnLogin, enabled) = [RACSignal combineLatest:@[ self.tfUsername.rac_textSignal, self.tfPassword.rac_textSignal ] reduce:^id(RACTuple *fields) { NSString *username = fields.first; NSString *password = fields.second; return @(username.length > 0 && password.length > 0); }]; Combining and reducing Signals

Slide 53

Slide 53 text

RAC(self.btnLogin, enabled) = [RACSignal combineLatest:@[ self.tfUsername.rac_textSignal, self.tfPassword.rac_textSignal ] reduce:^id(RACTuple *fields) { NSString *username = fields.first; NSString *password = fields.second; return @(username.length > 0 && password.length > 0); }]; Combining and reducing Signals combineLate st: reduce: Bind rac_textSign al rac_textSign al

Slide 54

Slide 54 text

RAC(self.lblTimeStamp, text) = [[[[RACSignal interval:1] startWith:[NSDate date]] map:^id(NSDate *value) { NSDateComponents *dateComponents = [[NSCalendar currentCalendar] components:(NSMinuteCalendarUnit| NSSecondCalendarUnit) fromDate:value]; return [NSString stringWithFormat:@"%d:%02d", dateComponents.minute, dateComponents.second]; }] deliverOn:[RACScheduler mainThreadScheduler] ]; Working With Timers  And Schedulers

Slide 55

Slide 55 text

Non-FRP Approach [client logInWithSuccess:^{ [client loadCachedMessagesWithSuccess:^(NSArray *messages) { [client fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMsgs) { NSLog(@"Fetched all messages."); } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }]; Reducing chains of callbacks

Slide 56

Slide 56 text

Non-FRP Approach [client logInWithSuccess:^{ [client loadCachedMessagesWithSuccess:^(NSArray *messages) { [client fetchMessagesAfterMessage:messages.lastObject success:^(NSArray *nextMsgs) { NSLog(@"Fetched all messages."); } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }]; } failure:^(NSError *error) { [self presentError:error]; }]; Reducing chains of callbacks Using ReactiveCocoa [[[[client logIn] sequenceNext:^{ return [client loadCachedMessages]; }] flattenMap:^(NSArray *messages) { return [client fetchMessagesAfterMessage: messages.lastObject]; }] subscribeError:^(NSError *error) { [self presentError:error]; } completed:^{ NSLog(@"Fetched all messages."); }];

Slide 57

Slide 57 text

Using switchToLatest RACSubject *letters = [RACSubject subject]; RACSubject *numbers = [RACSubject subject]; RACSubject *signalOfSignals = [RACSubject subject]; RACSignal *switched = [signalOfSignals switchToLatest]; // Outputs: A B 1 D [switched subscribeNext:^(NSString *x) { NSLog(@"%@", x); }]; [signalOfSignals sendNext:letters]; [letters sendNext:@"A"]; [letters sendNext:@"B"]; [signalOfSignals sendNext:numbers]; [letters sendNext:@"C"]; [numbers sendNext:@"1"]; [signalOfSignals sendNext:letters]; [numbers sendNext:@"2"]; [letters sendNext:@"D"];

Slide 58

Slide 58 text

Where next? You can find full documentation on GitHub repo of this project: http:/ /github.com/ReactiveCocoa/ ReactiveCocoa Should take a look at Elm and meet some FRP theory
 http:/ /elm-lang.org/ Lookup brief material on Wikipedia or some blogs

Slide 59

Slide 59 text

What else? FRP-based languages and frameworks: Elm ClojureScript C# – Rx JavaScript – Flapjax, RxJS, Bacon.js, Java – RxJava Ruby – Frapuccino

Slide 60

Slide 60 text

(Thanks!)