Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
SIGNAL-ING OUT OF
CALLBACK HELL
whoami /Omer Iqbal @olenhad
Functional Reactive Programming
Compositional Event Systems? ^
WHY?
The world is asynchronous
Programs need to interact with the world
But we have Listeners/Observer/Delegate/Callback
Patterns! Life's good! Go away!
// Yeah, the empire still uses Objective C
@protocol DeathStarDelegate {
- (void)didBlowUp;
}
// In DeathStar
@property (n...
PROBLEMS?
Unpredictable Order
Missing Events
Cleaning up listeners
Accidental
Recursion
MESSY STATE Eww
Multhreading OMG
Chaining dependent operations
"our intellectual powers are rather geared to master static
relations and that our powers to visualize processes
evolving ...
ENTER FRP/COMPOSITIONAL EVENT
SYSTEMS
Imperative programming describes computations as a series
of actions modifying program state
var numbers = [1,2,3,4,5];
va...
In functional programming we describe what we want rather
than how we want it done
var numbers = [1,2,3,4,5];
var even = n...
In FP we model computations as transformations of values
Declarative
Pure
Threadsafe
Composable
FRP extends this principle to asynchronous flows
SIGNALS
Representing a stream of values (over time)
e.g Async operations like API calls/UI Input/Timer RETURN
Signals
Send...
Signals can be subscribed to
[lannisterSignal subscribeNext:^(NSString *name){
NSLog(@"%@ is a true Lannister", name);
}];...
Creating Signals
- (RACSignal *)signInSignal
{
return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscri
[...
I know what you're thinking
COMPOSITION!
Signals like values can be transformed via higher order
functions!
Signal A -> Signal B
map
[lannisterSignal map:^NSNumber *(NSString *name){
return @(name.length);
}];
Signal A -> predicate? -> Signal A
filter
[lannisterSignal filter:^BOOL (NSString *name){
return ![name isEqualToString:@"...
Merge
RACSignal *contenders =
[RACSignal merge:@[lannisters, baratheons, starks, tyrells]];
Signal of Signals
[khaleesiSignal map:^RACSignal *(NSString *name){
return [[Khaleesi sharedInstance] fetchDragons];
}];
flatMap!
flatten: Signal (Signal A) -> Signal A
map: Signal A -> Signal B
psst... Also called bind. Shoutout to all the Ha...
Chaining dependent async operations
[[[[client logIn]
then:^{
return [client loadCachedMessages];
}]
flattenMap:^(NSArray ...
PIPELINES!
Declarative! => Clear Ordering
Composable!
No explicit state machine to manage!
Unified interface for Async events
BUT!
Not a silver bullet
Hot Signals vs Cold Signals
GOOD NEWS!
RAC3 uses Signal and SignalProducer types to distinguish
SIMPLE, NOT EASY THANKS RICH HICKEY!
Simple vs Complex
Easy vs Hard
questions? answers : end;
Signal ing out of callback hell
Upcoming SlideShare
Loading in …5
×

Signal ing out of callback hell

301 views

Published on

Async processes are hard to reason about. Especially when you're debugging them under four layers of nested callbacks. From handling complex UI interactions to coordinating parallel tasks, programming in an async world can be frustrating, especially if you're using an imperative programming languange/framework with mutable state.

This talk will examine how Functional Reactive Programming (FRP) provides a solution to these problems. By modelling async flows as streams of values, and performing transformations on those streams, FRP enables such processes to be written in a safer, declarative manner. This talk would use ReactiveCocoa and how it aids development on iOS and Mac as a case study.

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Signal ing out of callback hell

  1. 1. SIGNAL-ING OUT OF CALLBACK HELL whoami /Omer Iqbal @olenhad
  2. 2. Functional Reactive Programming Compositional Event Systems? ^
  3. 3. WHY? The world is asynchronous Programs need to interact with the world
  4. 4. But we have Listeners/Observer/Delegate/Callback Patterns! Life's good! Go away!
  5. 5. // Yeah, the empire still uses Objective C @protocol DeathStarDelegate { - (void)didBlowUp; } // In DeathStar @property (nonatomic, weak) id <DeathStarDelegate> delegate // When Blowing up [self.delegate didBlowUp]; // In DarthVader who implements DeathStarDelegate - (void)didBlowUp { NSLog(@"Need to hire better stormtroopers"); }
  6. 6. PROBLEMS? Unpredictable Order Missing Events Cleaning up listeners Accidental Recursion MESSY STATE Eww Multhreading OMG
  7. 7. Chaining dependent operations
  8. 8. "our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed" Dijkstra on GOTO
  9. 9. ENTER FRP/COMPOSITIONAL EVENT SYSTEMS
  10. 10. Imperative programming describes computations as a series of actions modifying program state var numbers = [1,2,3,4,5]; var even = []; numbers.forEach(function(n) { if (n % 2 == 0) { even.push(n); } }); console.log(even);
  11. 11. In functional programming we describe what we want rather than how we want it done var numbers = [1,2,3,4,5]; var even = numbers.filter(function(n){ return n % 2 == 0; });
  12. 12. In FP we model computations as transformations of values Declarative Pure Threadsafe Composable
  13. 13. FRP extends this principle to asynchronous flows
  14. 14. SIGNALS Representing a stream of values (over time) e.g Async operations like API calls/UI Input/Timer RETURN Signals Sends three kinds of events Next Error Completed
  15. 15. Signals can be subscribed to [lannisterSignal subscribeNext:^(NSString *name){ NSLog(@"%@ is a true Lannister", name); }]; [lannisterSignal sendNext:@"Cersei"]; [lannisterSignal sendNext:@"Jamie"]; [lannisterSignal sendCompleted]; [lannisterSignal sendNext:@"Tyrion"]; // Nothing logged here. Sorry Tyrion
  16. 16. Creating Signals - (RACSignal *)signInSignal { return [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscri [self.signInService signInWithUsername:self.txtUsername.text password:self.txtPassword.text complete:^(BOOL status, NSError *error) if (error) { [subscriber sendError:error]; } else { [subscriber sendNext:@(status)]; [subscriber sendCompleted]; } }]; return nil;
  17. 17. I know what you're thinking
  18. 18. COMPOSITION! Signals like values can be transformed via higher order functions!
  19. 19. Signal A -> Signal B map [lannisterSignal map:^NSNumber *(NSString *name){ return @(name.length); }];
  20. 20. Signal A -> predicate? -> Signal A filter [lannisterSignal filter:^BOOL (NSString *name){ return ![name isEqualToString:@"Tyrion"]; }];
  21. 21. Merge RACSignal *contenders = [RACSignal merge:@[lannisters, baratheons, starks, tyrells]];
  22. 22. Signal of Signals [khaleesiSignal map:^RACSignal *(NSString *name){ return [[Khaleesi sharedInstance] fetchDragons]; }];
  23. 23. flatMap! flatten: Signal (Signal A) -> Signal A map: Signal A -> Signal B psst... Also called bind. Shoutout to all the Haskell folks
  24. 24. Chaining dependent async operations [[[[client logIn] then:^{ return [client loadCachedMessages]; }] flattenMap:^(NSArray *messages) { return [client fetchMessagesAfterMessage:messages.lastObject]; }] subscribeError:^(NSError *error) { [self presentError:error]; } completed:^{ NSLog(@"Fetched all messages."); }];
  25. 25. PIPELINES!
  26. 26. Declarative! => Clear Ordering Composable! No explicit state machine to manage! Unified interface for Async events
  27. 27. BUT! Not a silver bullet Hot Signals vs Cold Signals
  28. 28. GOOD NEWS! RAC3 uses Signal and SignalProducer types to distinguish
  29. 29. SIMPLE, NOT EASY THANKS RICH HICKEY! Simple vs Complex Easy vs Hard
  30. 30. questions? answers : end;

×