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 programming for UI
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Teddy Ku
November 14, 2018
Programming
2.9k
1
Share
Functional programming for UI
Turn the pyramid of doom into a line of happiness
Teddy Ku
November 14, 2018
More Decks by Teddy Ku
See All by Teddy Ku
Concurrency in Swift
tkuichooseyou
2
2.6k
ReactiveSwift
tkuichooseyou
0
110
Other Decks in Programming
See All in Programming
「Linuxサーバー構築標準教科書」を読んでみた #ツナギメオフライン.7
akase244
0
1.4k
AWS re:Invent 2025の少し振り返り + DevOps AgentとBacklogを連携させてみた
satoshi256kbyte
3
160
ハンズオンで学ぶクラウドネイティブ
tatsukiminami
0
130
NakouPAY説明用
annouim0
0
170
クラウドネイティブなエンジニアに向ける Raycastの魅力と実際の活用事例
nealle
2
200
Back to the roots of date
jinroq
0
100
〜バイブコーディングを超えて〜 チームで実験し続けたAI駆動開発
tigertora7571
0
110
セグメントとターゲットを意識するプロポーザルの書き方 〜採択の鍵は、誰に刺すかを見極めるマーケティング戦略にある〜
m3m0r7
PRO
0
550
Vibe NLP for Applied NLP
inesmontani
PRO
0
430
forteeの改修から振り返るPHPerKaigi 2026
muno92
PRO
3
290
レガシーPHP転生 〜父がドメインエキスパートだったのでDDD+Claude Codeでチート開発します〜
panda_program
0
970
HTML-Aware ERB: The Path to Reactive Rendering @ RubyKaigi 2026, Hakodate, Japan
marcoroth
0
140
Featured
See All Featured
Chasing Engaging Ingredients in Design
codingconduct
0
170
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.5k
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
490
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
450
Crafting Experiences
bethany
1
110
Gemini Prompt Engineering: Practical Techniques for Tangible AI Outcomes
mfonobong
2
370
Reality Check: Gamification 10 Years Later
codingconduct
0
2.1k
Mind Mapping
helmedeiros
PRO
1
150
How People are Using Generative and Agentic AI to Supercharge Their Products, Projects, Services and Value Streams Today
helenjbeal
1
160
Mozcon NYC 2025: Stop Losing SEO Traffic
samtorres
0
210
The World Runs on Bad Software
bkeepers
PRO
72
12k
Transcript
Teddy Ku 'VODUJPOBMQSPHSBNNJOHGPS6*
2 Copyright © Merpay, Inc. All Rights Reserved. 5FEEZ,V !ULVJDIPPTFZPV
!ULVJDIPPTFZPV 4UBUVT
3 Copyright © Merpay, Inc. All Rights Reserved. 'FBUVSF 0OCPBSEJOHUVUPSJBMT
4 Copyright © Merpay, Inc. All Rights Reserved. 'FBUVSF 0OCPBSEJOHUVUPSJBMT
5 0OCPBSEJOHUVUPSJBMT Copyright © Merpay, Inc. All Rights Reserved.
6 Copyright © Merpay, Inc. All Rights Reserved. class BalloonView:
UIView { var onTapped: (() -> Void)? var contentView: UIView func show() { /* ... */ } func dismiss() { /* ... */ } /* ... */ }
7 Copyright © Merpay, Inc. All Rights Reserved. class ViewController:
UIViewController { func showTutorialFlow() { let tutorialOne = tutorialOneBalloonView() let tutorialTwo = tutorialTwoBalloonView() let tutorialThree = tutorialThreeBalloonView() tutorialOne.onTapped = { [weak tutorialOne] in tutorialOne?.dismiss() tutorialTwo.show() } tutorialTwo.onTapped = { [weak tutorialTwo] in tutorialTwo?.dismiss() tutorialThree.show() } tutorialThree.onTapped = { [weak self, weak tutorialThree] in tutorialThree?.dismiss() self?.hideGrayOverlay { } } showGrayOverlay { tutorialOne.show() } }
8 Copyright © Merpay, Inc. All Rights Reserved. class ViewController:
UIViewController { func showTutorialFlow() { let tutorialOne = tutorialOneBalloonView() let tutorialTwo = tutorialTwoBalloonView() let tutorialThree = tutorialThreeBalloonView() %PO`UXBOUUPJOTUBOUJBUFFWFSZUIJOHVQGSPOU 0OMZOFFEPOFWJFXBUBUJNF
9 Copyright © Merpay, Inc. All Rights Reserved. 3FXSJUFPOFWJFXBUBUJNF
class ViewController: UIViewController { func showTutorialFlow() { let tutorialOne =
tutorialOneBalloonView() tutorialOne.onTapped = { [weak tutorialOne] in tutorialOne?.dismiss() let tutorialTwo = tutorialTwoBalloonView() tutorialTwo.onTapped = { [weak tutorialTwo] in tutorialTwo?.dismiss() let tutorialThree = tutorialThreeBalloonView() tutorialThree.onTapped = { [weak self, weak tutorialThree] in tutorialThree?.dismiss() self?.hideGrayOverlay { } } tutorialThree.show() } tutorialTwo.show() } showGrayOverlay { tutorialOne.show() } } 10 Copyright © Merpay, Inc. All Rights Reserved. Pyramid of doom
11 Copyright © Merpay, Inc. All Rights Reserved. /FTUFEDMPTVSFT )PXUPEFBMXJUIUIFN
12 Copyright © Merpay, Inc. All Rights Reserved. 'VODUJPOTJOGVODUJPOT -FU`TVTFGVODUJPOT
'VODUJPOBM1SPHSBNNJOH
13 Copyright © Merpay, Inc. All Rights Reserved. 5IJOLUPQEPXO 8IBUXPVMEUIFJEFBMTPMVUJPOMPPLMJLF
14 Copyright © Merpay, Inc. All Rights Reserved. func showTutorialFlow()
{ let tutorialBalloon = tutorialOneBalloonView() let transitions = tutorialBalloon.onTapped({ inputBalloonView in inputBalloonView?.dismiss() return tutorialTwoBalloonView() }) >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialThreeBalloonView() } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFourBalloonView() } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFiveBalloonView() } >>> { [weak self] inputBalloonView in inputBalloonView?.dismiss() self?.hideGrayOverlay { } return nil } tutorialBalloon.show(onTapped: transitions) } $PNQPTBCMFUSBOTJUJPOGVODUJPOT
15 Copyright © Merpay, Inc. All Rights Reserved. )PXXPVMEXFJNQMFNFOUUIJT
16 Copyright © Merpay, Inc. All Rights Reserved. typealias BalloonTransition
= (BalloonView?) -> BalloonView? // associativity: right infix operator >>>: FunctionArrowPrecedence func >>> ( transitionOne: @escaping BalloonTransition, transitionTwo: @escaping BalloonTransition) -> BalloonTransition { return { balloonView in balloonView?._nextTransition = transitionTwo return transitionOne(balloonView) } } 1 >>> (2 >>> (3 >>> (4 >>> 5)))
17 Copyright © Merpay, Inc. All Rights Reserved. func >>>
( transitionOne: @escaping BalloonTransition, transitionTwo: @escaping BalloonTransition) -> BalloonTransition { return { balloonView in balloonView?._nextTransition = transitionTwo return transitionOne(balloonView) } } 1 >>> (2 >>> (3 >>> (4 >>> 5))) func showTutorialFlow() { let tutorialBalloon = tutorialOneBalloonView() let transitions = tutorialBalloon.onTapped({ inputBalloonView in inputBalloonView?.dismiss() return tutorialTwoBalloonView() }) >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialThreeBalloonView() } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFourBalloonView() } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFiveBalloonView() } >>> { [weak self] inputBalloonView in inputBalloonView?.dismiss() self?.hideGrayOverlay { } return nil } tutorialBalloon.show(onTapped: transitions) }
18 Copyright © Merpay, Inc. All Rights Reserved. func showTutorialFlow()
{ let tutorialBalloon = tutorialOneBalloonView() let transitions = tutorialBalloon.onTapped({ inputBalloonView in inputBalloonView?.dismiss() return tutorialTwoBalloonView() }) >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialThreeBalloonView() } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFourBalloonView() } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFiveBalloonView() } >>> { [weak self] inputBalloonView in inputBalloonView?.dismiss() self?.hideGrayOverlay { } return nil } tutorialBalloon.show(onTapped: transitions) } func >>> ( transitionOne: @escaping BalloonTransition, transitionTwo: @escaping BalloonTransition) -> BalloonTransition { return { balloonView in balloonView?._nextTransition = transitionTwo return transitionOne(balloonView) } } } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFiveBalloonView() } >>> { [weak self] inputBalloonView in inputBalloonView?.dismiss() self?.hideGrayOverlay { } return nil } -BTUUXPDMPTVSFT
Copyright © Merpay, Inc. All Rights Reserved. { balloon4 in
balloon4.nextTransition = { [weak self] balloon5 in balloon5?.dismiss() self?.hideGrayOverlay { } return nil } balloon4?.dismiss() return tutorialFiveBalloonView() } } >>> { inputBalloonView in inputBalloonView?.dismiss() return tutorialFiveBalloonView() } >>> { [weak self] inputBalloonView in inputBalloonView?.dismiss() self?.hideGrayOverlay { } return nil } FYFDVUFXIFOCBMMPPOJTUBQQFE FYFDVUFXIFO CBMMPPOJTUBQQFE 8IBUEPFTSFUVSOTBDMPTVSF OPUBDUVBMDPEF
Copyright © Merpay, Inc. All Rights Reserved. balloon3.nextTransition = {
balloon4 in balloon4.nextTransition = { [weak self] balloon5 in balloon5?.dismiss() self?.hideGrayOverlay { } return nil } balloon4?.dismiss() return tutorialFiveBalloonView() } balloon3?.dismiss() return tutorialFourBalloonView() GVODUJPOXJMMTFUUIFDMPTVSFUP UIFQSFWJPVT#BMMPPO7JFX 8IBUEPFT OPUBDUVBMDPEF
Copyright © Merpay, Inc. All Rights Reserved. balloon2.nextTransition = {
balloon3 in balloon3.nextTransition = { balloon4 in balloon4.nextTransition = { [weak self] balloon5 in balloon5?.dismiss() self?.hideGrayOverlay { } return nil } balloon4?.dismiss() return tutorialFiveBalloonView() } balloon3?.dismiss() return tutorialFourBalloonView() } balloon2?.dismiss() return tutorialThreeBalloonView() 8IBUEPFT OPUBDUVBMDPEF
Copyright © Merpay, Inc. All Rights Reserved. tutorialBalloon.show(onTapped: { balloon1
in balloon1.nextTransition = { balloon2 in balloon2.nextTransition = { balloon3 in balloon3.nextTransition = { balloon4 in balloon4.nextTransition = { [weak self] balloon5 in balloon5?.dismiss() self?.hideGrayOverlay { } return nil } balloon4?.dismiss() return tutorialFiveBalloonView() } balloon3?.dismiss() return tutorialFourBalloonView() } balloon2?.dismiss() return tutorialThreeBalloonView() } balloon1?.dismiss() return tutorialTwoBalloonView() }) 8IBUEPFT OPUBDUVBMDPEF
Copyright © Merpay, Inc. All Rights Reserved. tutorialBalloon.show(onTapped: { balloon1
in balloon1.nextTransition = { balloon2 in balloon2.nextTransition = { balloon3 in balloon3.nextTransition = { balloon4 in balloon4.nextTransition = { [weak self] balloon5 in balloon5?.dismiss() self?.hideGrayOverlay { } return nil } balloon4?.dismiss() return tutorialFiveBalloonView() } balloon3?.dismiss() return tutorialFourBalloonView() } balloon2?.dismiss() return tutorialThreeBalloonView() } balloon1?.dismiss() return tutorialTwoBalloonView() })
24 Copyright © Merpay, Inc. All Rights Reserved. .JTTJPOBDDPNQMJTIFE 3FBEBCMFDPEF
0OMZPOF#BMMPPO7JFXJONFNPSZ
25 Copyright © Merpay, Inc. All Rights Reserved. $VSSZJOH func
add(x: Int) -> ((Int) -> Int) { return { y in return x + y } } // Removed in Swift 3 // https://github.com/apple/swift-evolution/blob/master/proposals/0002-remove-currying.md func foo(x: Int)(y: Int)
26 Copyright © Merpay, Inc. All Rights Reserved. typealias Filter
= (CIImage) -> CIImage let myFilter = blur(blurRadius) >>> colorOverlay(overlayColor) let result = myFilter(image) *OTQJSBUJPO'VODUJPOBM4XJGU PCKDJP
27 Copyright © Merpay, Inc. All Rights Reserved. 4XJGU0CKFDUJWF$
28 Copyright © Merpay, Inc. All Rights Reserved. 5IBOLZPV HJUIVCDPNNFSDBSJ#BMMPPO7JFX