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
87
Lessons From Becoming an SDK Developer
oscarswanros
0
60
Objective-C & Swift: Interoperability Tips and Tricks
oscarswanros
0
150
What Lies Under The Syntax Sugar
oscarswanros
0
210
Apps Para iOS: De Diseño a Implementación
oscarswanros
0
79
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
180
Android Elements & Design Patterns
oscarswanros
0
65
Other Decks in Programming
See All in Programming
Quality Gates in the Age of Agentic Coding
helmedeiros
PRO
1
120
iOS開発スターターキットの作り方
akidon0000
0
230
「次に何を学べばいいか分からない」あなたへ──若手エンジニアのための学習地図
panda_program
3
700
CLI ツールを Go ライブラリ として再実装する理由 / Why reimplement a CLI tool as a Go library
ktr_0731
3
930
대규모 트래픽을 처리하는 프론트 개발자의 전략
maryang
0
110
AWS Summit Japan 2024と2025の比較/はじめてのKiro、今あなたは岐路に立つ
satoshi256kbyte
1
260
Gemini CLIの"強み"を知る! Gemini CLIとClaude Codeを比較してみた!
kotahisafuru
3
890
Go製CLIツールをnpmで配布するには
syumai
2
1k
LLMは麻雀を知らなすぎるから俺が教育してやる
po3rin
3
1.9k
Workers を定期実行する方法は一つじゃない
rokuosan
0
140
TypeScriptでDXを上げろ! Hono編
yusukebe
4
920
[Codecon - 2025] Como não odiar seus testes
camilacampos
0
100
Featured
See All Featured
The Straight Up "How To Draw Better" Workshop
denniskardys
235
140k
[RailsConf 2023] Rails as a piece of cake
palkan
56
5.7k
Principles of Awesome APIs and How to Build Them.
keavy
126
17k
Being A Developer After 40
akosma
90
590k
Automating Front-end Workflow
addyosmani
1370
200k
Speed Design
sergeychernyshev
32
1.1k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
Producing Creativity
orderedlist
PRO
346
40k
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
3.9k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
21
1.4k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
46
7.5k
The Illustrated Children's Guide to Kubernetes
chrisshort
48
50k
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