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
140
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Functional Reactive Programming
Functional Reactive Programming 101.
Oscar Swanros
February 18, 2015
More Decks by Oscar Swanros
See All by Oscar Swanros
Applied Concurrency: NOT from the ground up
oscarswanros
0
110
Lessons From Becoming an SDK Developer
oscarswanros
0
81
Objective-C & Swift: Interoperability Tips and Tricks
oscarswanros
0
170
What Lies Under The Syntax Sugar
oscarswanros
0
260
Apps Para iOS: De Diseño a Implementación
oscarswanros
0
97
Becoming a Better iOS Developer Through Tooling
oscarswanros
0
2.8k
Mejores Prácitcas Para el Desarrollo de Aplicaciones iOS con Swift
oscarswanros
0
150
Architecting iOS Apps for Fun & Profit
oscarswanros
0
210
Android Elements & Design Patterns
oscarswanros
0
84
Other Decks in Programming
See All in Programming
AutonomyとControlのあいだ:Graflowで記述するAIエージェント協調
myui
0
120
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
160
AIとASP.NET Coreで雑Webアプリを作った話
mayuki
0
500
依存関係から依存物へ―Dependencyという言葉の歴史をひも解く
j_lee
0
110
その問い、本当に正しいですか?AI時代のエンジニアに必要な哲学と認知科学 / ai-philosophy-cognitive-science
minodriven
6
4k
The ROI of Quarkus for Spring Boot Applications
hollycummins
0
110
Oxcを導入して開発体験が向上した話
yug1224
4
310
肥大化するレガシーコードに立ち向かうためのインターフェース分離と依存の逆転 / JJUG CCC 2026 Spring
hirokunimaeta
0
530
Dataformのリポジトリを立ち上げるときにまずやること / dataform-day0-2026
snhryt
0
150
Developing with AI Agents — Codex, Claude Code & Cowork Practical Guide
x5gtrn
PRO
0
1.3k
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
260
ADKを使って簡単にAIエージェントを作ってみよう
k1mu21
0
260
Featured
See All Featured
WCS-LA-2024
lcolladotor
0
630
B2B Lead Gen: Tactics, Traps & Triumph
marketingsoph
0
140
Large-scale JavaScript Application Architecture
addyosmani
515
110k
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
1.1k
SEOcharity - Dark patterns in SEO and UX: How to avoid them and build a more ethical web
sarafernandez
0
200
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
530
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
Lightning talk: Run Django tests with GitHub Actions
sabderemane
0
200
SEO for Brand Visibility & Recognition
aleyda
0
4.6k
Raft: Consensus for Rubyists
vanstee
141
7.5k
Fashionably flexible responsive web design (full day workshop)
malarkey
408
66k
Ruling the World: When Life Gets Gamed
codingconduct
0
250
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