Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Functional Reactive Programming
Search
Oscar Swanros
February 18, 2015
Programming
1
100
Functional Reactive Programming
Functional Reactive Programming 101.
Oscar Swanros
February 18, 2015
Tweet
Share
More Decks by Oscar Swanros
See All by Oscar Swanros
Applied Concurrency: NOT from the ground up
oscarswanros
0
91
Lessons From Becoming an SDK Developer
oscarswanros
0
61
Objective-C & Swift: Interoperability Tips and Tricks
oscarswanros
0
150
What Lies Under The Syntax Sugar
oscarswanros
0
220
Apps Para iOS: De Diseño a Implementación
oscarswanros
0
80
Becoming a Better iOS Developer Through Tooling
oscarswanros
0
2.8k
Mejores Prácitcas Para el Desarrollo de Aplicaciones iOS con Swift
oscarswanros
0
120
Architecting iOS Apps for Fun & Profit
oscarswanros
0
190
Android Elements & Design Patterns
oscarswanros
0
67
Other Decks in Programming
See All in Programming
Playwrightはどのようにクロスブラウザをサポートしているのか
yotahada3
7
2.3k
Le côté obscur des IA génératives
pascallemerrer
0
130
iOS 17で追加されたSubscriptionStoreView を利用して5分でサブスク実装チャレンジ
natmark
0
650
Web Components で実現する Hotwire とフロントエンドフレームワークの橋渡し / Bridging with Web Components
da1chi
3
2k
私達はmodernize packageに夢を見るか feat. go/analysis, go/ast / Go Conference 2025
kaorumuta
2
500
XP, Testing and ninja testing ZOZ5
m_seki
3
400
明日から始めるリファクタリング
ryounasso
0
120
ポスターセッション: 「まっすぐ行って、右!」って言ってラズパイカーを動かしたい 〜生成AI × Raspberry Pi Pico × Gradioの試作メモ〜
komofr
0
1.1k
タスクの特性や不確実性に応じた最適な作業スタイルの選択(ペアプロ・モブプロ・ソロプロ)と実践 / Optimal Work Style Selection: Pair, Mob, or Solo Programming.
honyanya
3
150
デミカツ切り抜きで面倒くさいことはPythonにやらせよう
aokswork3
0
210
After go func(): Goroutines Through a Beginner’s Eye
97vaibhav
0
240
なぜあの開発者はDevRelに伴走し続けるのか / Why Does That Developer Keep Running Alongside DevRel?
nrslib
3
380
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
84
9.2k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
30
2.9k
Optimizing for Happiness
mojombo
379
70k
How to train your dragon (web standard)
notwaldorf
96
6.3k
Mobile First: as difficult as doing things right
swwweet
224
10k
Docker and Python
trallard
46
3.6k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
9
850
Fashionably flexible responsive web design (full day workshop)
malarkey
407
66k
Code Review Best Practice
trishagee
72
19k
Making Projects Easy
brettharned
119
6.4k
Principles of Awesome APIs and How to Build Them.
keavy
127
17k
A better future with KSS
kneath
239
17k
Transcript
Func%onal)Reac%ve)Programming Oscar&Swanros MobileCoder.mx mobilecoder.mx,-2015 1
@Swanros h"p:/ /swanros.com mobilecoder.mx,-2015 2
I"got"bored. mobilecoder.mx,-2015 3
Un#l... mobilecoder.mx,-2015 4
WWDC$'14 mobilecoder.mx,-2015 5
I'm$running$away$from$OOP$and$the$ MVC$pa9ern. mobilecoder.mx,-2015 6
And$also$a$li*le$bit$ of... mobilecoder.mx,-2015 7
typedef (^myBlock)(BOOL isThisCool) = ^void() { // }; mobilecoder.mx,-2015 8
Callback'hell,'anyone? mobilecoder.mx,-2015 9
Because'it'gets'boring'quickly... ! mobilecoder.mx,-2015 10
Enter&FRP. mobilecoder.mx,-2015 11
Func%onal)Reac%ve)Programming = Func%onal)Programming)+)Reac%ve)Programming mobilecoder.mx,-2015 12
Func%onal)Programming In#a#purely'func+onal#language,#f(x)#will#return#the#same#value#for# the#same#x. Always. mobilecoder.mx,-2015 13
Reac%ve'Programming In#a#reac%ve#language,#y=f(x) y!will!always!stay!up!to!date!when!x! changes. mobilecoder.mx,-2015 14
mobilecoder.mx,-2015 15
FRP!is!about!datatypes!that! represent!a!value!over!&me. mobilecoder.mx,-2015 16
At#the#core#of#FRP#are#Signals. mobilecoder.mx,-2015 17
A"Signal"is"a"value"that"changes"over()me. mobilecoder.mx,-2015 18
done := make(chan bool) watcher := notificator.New() for { select
{ case newText := <-watcher.Next: fmt.Println(newText) case error := <-watcher.Error: log.Fatal(error) } } <-done mobilecoder.mx,-2015 19
[self.emailTextField.rac_textSignal subscribeNext:^(id value) { NSLog(@"%@", value); }]; mobilecoder.mx,-2015 20
mobilecoder.mx,-2015 21
@interface ViewController()<UITextFieldDelegate> // ... self.emailTextField.delegate = self; // ... -(BOOL)textField:(UITextField
*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { NSLog(@"%@", [textField.text stringByAppendingString:string]); return YES; } mobilecoder.mx,-2015 22
[self.emailTextField.rac_textSignal subscribeNext:^(id value) { NSLog(@"%@", value); }]; mobilecoder.mx,-2015 23
// 1 RACSignal *usernameTextSignal = self.usernameTextField.rac_textSignal; RACSignal *passwordTextSignal = self.passwordTextField.rac_textSignal;
// 2 RACSignal *validUsernameSignal = [[usernameTextSignal map:^id(NSString *username) { return @([self isValidUsername:username]); }] distinctUntilChanged]; RACSignal *validPasswordSignal = [[passwordTextSignal map:^id(NSString *password) { return @([self isValidPassword:password]); }] distinctUntilChanged]; // 3 RAC(self.usernameTextField, backgroundColor) = [validUsernameSignal map:^id(NSNumber *usernameValid) { return [usernameValid boolValue] ? [UIColor greenColor] : [UIColor redColor]; }]; RAC(self.passwordTextField, backgroundColor) = [validPasswordSignal map:^id(NSNumber *passwordValid) { return [passwordValid boolValue] ? [UIColor greenColor] : [UIColor redColor]; }]; // 4 [[RACSignal combineLatest:@[validUsernameSignal, validPasswordSignal] reduce:^id(NSNumber *usernameValid, NSNumber *passwordValid){ return @([usernameValid boolValue] == YES && [passwordValid boolValue] == YES); }] subscribeNext:^(NSNumber *loginButtonActive) { self.loginButton.enabled = [loginButtonActive boolValue]; }]; mobilecoder.mx,-2015 24
mobilecoder.mx,-2015 25
Func%onal)Reac%ve)Programming)lets)you)be)more)concise)with)your)code. mobilecoder.mx,-2015 26
Focus&on&what&you&want&to&do, and$not$on$how$to$do$it. mobilecoder.mx,-2015 27
(That's(the(Func.onal(mo#o.) mobilecoder.mx,-2015 28
Resources? mobilecoder.mx,-2015 29
Ruby:&frapuccino class Button def push emit(:pushed) end end button =
Button.new stream = Frappuccino::Stream.new(button) counter = stream .map {|event| event == :pushed ? 1 : 0 } .inject(0) {|sum, n| sum + n } counter.now # => 0 button.push counter.now # => 1 mobilecoder.mx,-2015 30
JS:$RxJS var source = getStockData(); source .filter(function (quote) { return
quote.price > 30; }) .map(function (quote) { return quote.price; }) .forEach(function (price) { console.log('Prices higher than $30: $' + price); }); mobilecoder.mx,-2015 31
Learning(FRP(is(hard. mobilecoder.mx,-2015 32
But$it's$worth$it. mobilecoder.mx,-2015 33
Ques%ons? mobilecoder.mx,-2015 34