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
Alexander Voronov
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Oleksandr Voronov
September 15, 2015
Programming
1.2k
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Alexander Voronov
Swift: Going Functional
https://youtu.be/Dc9aKhs37BE
Oleksandr Voronov
September 15, 2015
More Decks by Oleksandr Voronov
See All by Oleksandr Voronov
Controllable Randomness in Unit Tests
alexandervoronov
1
81
Modularizing your iOS apps
alexandervoronov
0
190
TDD in Real World
alexandervoronov
1
280
Building CLI with Swift
alexandervoronov
1
350
Stanfy MadCode 10: From Java to Kotlin, from Objective-C to Swift
alexandervoronov
0
260
ReactiveCocoa
alexandervoronov
0
190
Other Decks in Programming
See All in Programming
XHTMLが残したもの
yosuke_furukawa
PRO
1
380
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
0
180
[DroidKaigi 26] How We Moved from Android Studio to Slack
thisaay
0
190
数年滞っていたダークモード対応をおよそ2週間で完了させる
chigichan24
0
660
The Good Stuff, Not the Slop: Engineering High-Quality Android Apps with Modern AI Tooling
danybony
0
150
ALB ログから Trace を気合で繋げる技術
fohte
7
860
MySQLとPostgreSQLって何が違うの?
akagami
PRO
0
160
LLMは4年分のCompose移行を再現できるのか?実プロダクト279件のXMLで探る自動化の境界線
makun
0
360
書籍「プロフェッショナルAI駆動開発」紹介スライド
juntaromatsumoto
0
960
ソフトウェアラスタライザ
fadis
1
780
「つくるAI」だけではバグは見つからない ~テストに必要な「見つけるAI」を分離させる戦略~
mfunaki
0
230
高専キャリア LT 発表内容
crysta1221
6
5.5k
Featured
See All Featured
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
840
We Have a Design System, Now What?
morganepeng
55
8.3k
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Site-Speed That Sticks
csswizardry
13
1.5k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
190
What the history of the web can teach us about the future of AI
inesmontani
PRO
1
680
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
How Software Deployment tools have changed in the past 20 years
geshan
1
34k
How to audit for AI Accessibility on your Front & Back End
davetheseo
0
520
Leo the Paperboy
mayatellez
8
2.2k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
10
1.3k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
63
45k
Transcript
Swift Rocks 2! Alexander Voronov iOS Developer @ Stanfy
Swift Going Functional
What is Functional Programming?
Functional Programming
Functional Programming • Higher-order functions
Functional Programming • Higher-order functions • Immutable states & pure
functions
Functional Programming • Higher-order functions • Immutable states & pure
functions • Modularity
Functional Programming • Higher-order functions • Immutable states & pure
functions • Modularity • Types
Swift Power
Swift Power
Swift Power • First Class Functions
Swift Power • First Class Functions • Currying
Swift Power • First Class Functions • Currying • Generics
Swift Power • First Class Functions • Currying • Generics
• Type Inference
Swift Power • First Class Functions • Currying • Generics
• Type Inference • Enums
First Class Functions func add(x: Int) -> Int -> Int
{ return { y in y + x } } let addOne = add(1) addOne(2) // 3
First Class Functions func addTwo(x: Int) -> Int { return
x + 2 } (1...5).map(addTwo) // [3, 4, 5, 6, 7]
Currying func add(a: Int)(b: Int) -> Int { return a
+ b } let addOne = add(1) let xs = 1...5 xs.map(addOne) // [2, 3, 4, 5, 6]
Currying func curry<A, B, C>(f: (A, B) -> C) ->
A -> B -> C { return { a in { b in f(a, b) } } }
Generics func printEach<T: SequenceType>(items: T) { for item in items
{ print(item) } } printEach(1...5) printEach(["one", "two", "three"])
Type Inference let x = 42.0 x.dynamicType // Double x
is Double // true
Type Inference var xs = [1, 5, 2, 4, 3]
xs.sort(<) print(xs) // [1, 2, 3, 4, 5]
Type Inference var xs = [1, 5, 2, 4, 3]
xs.sort(<) print(xs) // [1, 2, 3, 4, 5]
Type Inference let xs = [1, 5, 2, 4, 3]
let ys = xs.sorted(<) print(xs) // [1, 5, 2, 4, 3] print(ys) // [1, 2, 3, 4, 5]
Type Inference let xs = [1, 5, 2, 4, 3]
let ys = xs.sorted(<) print(xs) // [1, 5, 2, 4, 3] print(ys) // [1, 2, 3, 4, 5]
Enumerations enum Fruit: String { case Apple = "apple" case
Banana = "banana" case Cherry = "cherry" } Fruit.Apple.rawValue // "apple"
Enumerations enum ValidationResult { case Valid case NotValid(NSError) }
Enumerations enum MyApi { case xAuth(String, String) case GetUser(Int) }
extension MyApi: MoyaTarget { var baseURL: NSURL { return NSURL(string: "")! } var path: String { switch self { case .xAuth: return "/authorise" case .GetUser(let id): return "/user/\(id)" } } } https://github.com/Moya/Moya
Optionals enum Optional<T> { case None case Some(T) } var
x = 5 x = nil // Error!
Optional Chaining struct Dog { var name: String } struct
Person { var dog: Dog? } let dog = Dog(name: "Dodge") let person = Person(dog: dog) let dogName = person.dog?.name
Optional Chaining struct Dog { var name: String } struct
Person { var dog: Dog? } let dog = Dog(name: "Dodge") let person = Person(dog: dog) let dogName = person.dog?.name Optional Chaining
Functors, Applicatives, Monads
None
Functors, Applicatives, Monads let x = 2 x + 3
// == 5
Functors, Applicatives, Monads let x = 2 x + 3
// == 5 let y = Optional(2)
Functors let y = Optional(2) y + 3 // Error!
// Value of optional type // Optional<Int> not unwrapped
Functors let y = Optional(2) y.map { $0 + 3
} // Optional(5)
Functors func map<U>(f: T -> U) -> U? { switch
self { case .Some(let x): return f(x) case .None: return .None } }
Functors infix operator <^> { associativity left } func <^><T,
U>(f: T -> U, a: T?) -> U? { return a.map(f) }
Functors func <^><T, U>(f: T -> U, a: T?) ->
U? { return a.map(f) } let addOne = { $0 + 1 } addOne <^> Optional(2) // Optional(3)
Applicative func apply<U>(f: (T -> U)?) -> U? { switch
f { case .Some(let someF): return self.map(someF) case .None: return .None } }
Applicatives infix operator <*> { associativity left } func <*><T,
U>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) }
Applicatives infix operator <*> { associativity left } func <*><T,
U>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) } func add(a: Int)(b: Int) -> Int { return a + b }
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a
= add <^> Optional(2)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a
= add <^> Optional(2)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a
= add <^> Optional(2) let a: (b: Int) -> Int?
Monads typealias T = Double let f: T -> T
= { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 }
Monads typealias T = Double let f: T -> T
= { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 } f(g(4, 2))
Monads typealias T = Double let f: T -> T
= { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 } f(g(4, 2)) g: (T, T) -> T?
Monads typealias T = Double let f: T -> T
= { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 } f(g(4, 2)) g: (T, T) -> T? g(4, 2) >>- { f($0) }
Monads >>- == http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Monads func flatten<U>(a: U??) -> U? { switch a {
case .Some(let someA): return someA case .None: return .None } }
Monads func flatMap<U>(f: T -> U?) -> U? { return
flatten(map(f)) }
Monads func flatMap<U>(f: T -> U?) -> U? { return
flatten(map(f)) } func map<U>(f: T -> U) -> U?
Monads func flatMap<U>(f: T -> U?) -> U? { return
flatten(map(f)) } func map<U>(f: T -> U) -> U?
Monads func flatMap<U>(f: T -> U?) -> U? { return
flatten(map(f)) } func map<U>(f: T -> U) -> U? func map<U?>(f: T -> U?) -> U??
Monads infix operator >>- { associativity left } func >>-<T,
U>(a: T?, f: T -> U?) -> U? { return a.flatMap(f) }
Monads func half(a: Int) -> Int? { return a %
2 == 0 ? a / 2 : .None }
Monads func half(a: Int) -> Int? { return a %
2 == 0 ? a / 2 : .None } Optional(8) >>- half >>- half // Optional(2)
Monad Laws • Left Identity • Right Identity • Associativity
Left Identity Law let f = { Optional($0 + 1)
} let a = 1 let x = Optional(a) >>- f let y = f(a) x == y
Right Identity Law func create<T>(value: T) -> T? { return
Optional(value) } let x = Optional(1) >>- create let y = Optional(1) x == y
Associativity Law let double = { Optional(2 * $0) }
let triple = { Optional(3 * $0) } let x = Optional(1) >>- double >>- triple let y = Optional(1) >>- { double($0) >>- triple } let z = { Optional(1) >>- double }() >>- triple x == y y == z
Recap Functor map<U>(f: T -> U) -> M<U> Applicative apply<U>(f:
M<(T -> U)>) -> M<U> Monad flatMap<U>(f: T -> M<U>) -> M<U>
Pipes & Railways @ScottWlaschin
Pipes infix operator |> { associativity left } public func
|> <T, U>(x: T, f: T -> U) -> U { return f(x) } let addTwo = { $0 + 2 } let prodThree = { $0 * 3 } 5 |> addTwo |> prodThree |> print // 21
Pipes let transformedX = x |> addTwo |> prodThree |>
increment |> square |> pow VS (pow(square(increment(prodThree(addTwo(x))))))
Railways http://fsharpforfunandprofit.com/posts/recipe-part2/
Argo JSON Parser + Argo Runes
Argo Example extension Model: Decodable { static func decode(json: JSON)
-> Decoded<Model> { return Model.create <^> json <| "id" <*> json <| "room" <*> json <| "guest_name" <*> json <| "status" <*> json <| "label" <*> json <|? "user_comment" <*> json <| ["channel", "label"] <*> json <| "severity" <*> json <|| "epochs" <*> json <|| "body" } }
Argo Example let entities: [Model]? entities = data?.json() >>- {
$0["entities"] } >>- decode
Where Next?
Where Next • Functors, Applicatives and Monads in Pictures •
Railway Oriented Programming • Functional Programming in Swift (Objc.io) • Argo • Swiftz • RxSwift • ReactiveCocoa-3.0 • Haskell, F#, Erlang, Elm
Thanks!
Comments / Questions? @aleks_voronov a-voronov