Slide 1

Slide 1 text

Swift 5.7 in 5(-ish) minutes try! Swift DUB DUB 2022 ! Shai Mishali @freak4pc

Slide 2

Slide 2 text

Shorthand optional unwrapping if let extremelyLongOptionalVariable /" Do something with `extremelyLongOptionalVariable` } = extremelyLongOptionalVariable { 5.6

Slide 3

Slide 3 text

Shorthand optional unwrapping while let extremelyLongOptionalVariable { /" Do something with `extremelyLongOptionalVariable` } guard let extremelyLongOptionalVariable else { /" `extremelyLongOptionalVariable` isn’t available } if let extremelyLongOptionalVariable /" Do something with `extremelyLongOptionalVariable` } { 5.7

Slide 4

Slide 4 text

First-class Regular Expression let string = "017DC4" let regex = try! NSRegularExpression(pattern: #” # ? ([A-Fa - f0-9{2})([A-Fa - f0-9]{2})([A-Fa - f0-9]{2})"#) let matches = regex.matches(in: string, range: NSRange(location: 0, length: string.count)) guard let match = matches.f i rst, match.numberOfRanges = = 4 else { fatalError("Wrong number of matches") } print(string[Range(match.range(at: 0), in: string)!]) / / #017DC4 print(string[Range(match.range(at: 1), in: string)!]) / / 01 print(string[Range(match.range(at: 2), in: string)!]) / / 7D print(string[Range(match.range(at: 3), in: string)!]) / / C4 5.6

Slide 5

Slide 5 text

First-class Regular Expression let regex = /#'([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})([A-Fa-f0-9]{2})/ Super-powered by the Swift Compiler: Returns a strictly-typed tuple of the matches: guard let thing = try regex.wholeMatch(in: string) else { return } print(thing.0, thing.1, thing.2, thing.3) /" Prints: 017DC4 01 7D C4 Evaluated at compile-time: 5.7

Slide 6

Slide 6 text

First-class Regular Expression let regex = #/ #' (?[A-Fa-f0-9]{2}) (?[A-Fa-f0-9]{2}) (?[A-Fa-f0-9]{2}) /# You can even have NAMED matches: guard let thing = try regex.wholeMatch(in: string) else { return } print(thing.0, thing.firstHex, thing.secondHex, thing.thirdHex) /" Prints: 017DC4 01 7D C4 And the compiler will auto-synthesize a named tuple: 5.7

Slide 7

Slide 7 text

First-class Regular Expression let regex = #/ #' (?[A-Fa-f0-9]{2}) (?[A-Fa-f0-9]{2}) (?[A-Fa-f0-9]{2}) /# You can even have NAMED matches: guard let thing = try regex.wholeMatch(in: string) else { return } print(thing.0, thing.firstHex, thing.secondHex, thing.thirdHex) /" Prints: 017DC4 01 7D C4 And the compiler will auto-synthesize a named tuple: 5.7

Slide 8

Slide 8 text

First-class Regular Expression let regex = #/ #' (?[A-Fa-f0-9]{2}) (?[A-Fa-f0-9]{2}) (?[A-Fa-f0-9]{2}) /# You can even have NAMED matches: guard let thing = try regex.wholeMatch(in: string) else { return } print(thing.0, thing.firstHex, thing.secondHex, thing.thirdHex) /" Prints: 017DC4 01 7D C4 And the compiler will auto-synthesize a named tuple: HOLY MOLY " 5.7

Slide 9

Slide 9 text

First-class Regular Expression let regex = Regex { Optionally("#") Capture { Repeat(count: 2) { /[A-Za-z0-9]/ } } Capture { Repeat(count: 2) { /[A-Za-z0-9]/ } } Capture { Repeat(count: 2) { /[A-Za-z0-9]/ } } } For those who don’t feel comfortable with cryptic Regex syntax, There’s also an ultra-expressive result builder option: 5.7

Slide 10

Slide 10 text

async/await in top-level code @main struct MyAmazingCLI { static func main() async throws { try await someLongRunningCommand() } } Requires “hacking” a fake type and annotating as the @main entry point: 5.6

Slide 11

Slide 11 text

async/await in top-level code You can run concurrency-related command right at your main.swift: try await someLongRunningCommand() 5.7

Slide 12

Slide 12 text

Concrete-typed default values for generic expressions func pickElement(from elements: T = 1..%100) -+ T.Element? { elements.randomElement() } pickElement() /" 27 pickElement(from: ["A", "B", “C”]) /" B 5.7 func pickElement(from elements: T) -+ T.Element { elements.randomElement()! } pickElement(from: ["A", "B", “C"]) /" B 5.6

Slide 13

Slide 13 text

Massive generic improvements - Opaque Types accept arrays of opaque types return most possible variations of opaque types Until now we could use Opaque Types only for return types: They can now be used in other places that make sense, for example, arguments: struct MyView: View { var body: some View { Text("Hello!") } } func fillFuel(for vehicle: V) func fillFuel(for vehicle: some Vehicle) 5.6 5.7

Slide 14

Slide 14 text

Massive generic improvements - any accept arrays of opaque types return most possible variations of opaque types There’s also a new any keyword to better represent a case when “Any instance of kind X” could be used, opposed to some which must be a known concrete type func batchFillFuel(for vehicles: [some Vehicle]) batchFillFuel(for: [Car(), Car(), Car()]) func batchFillFuel(for vehicles: [any Vehicle]) batchFillFuel(for: [Car(), Truck(), Motorcycle()]) batchFillFuel(for: [Car(), Truck(), Motorcycle()]) 5.7

Slide 15

Slide 15 text

accept arrays of opaque types return most possible variations of opaque types any is basically the compiler-backed version for Type Erasure. Which means that in many cases, we won’t need to create type erasing types just to pass generics along: let sequence: AnySequence let sequence: any Sequence Massive generic improvements - any 5.6 5.7

Slide 16

Slide 16 text

accept arrays of opaque types return most possible variations of opaque types This also makes this dreaded error a thing of the past, in many cases: public protocol RequestType { associatedtype Route } func parseRequests(_ requests: [RequestType]) func parseRequests(_ requests: [any RequestType]) Massive generic improvements - any 5.6 5.7

Slide 17

Slide 17 text

Massive generic improvements Primary associated type for protocols protocol Vehicle { associatedtype Kind } struct TeslaModel3: Vehicle { typealias Kind = Electric } struct FordF150: Vehicle { typealias Kind = Gasoline } func fillFuel(for vehicle: V) where V.Kind =% Gasoline Constraining a speci ic kind of vehicle can get quite verbose: fillFuel(for: TeslaModel3()) fillFuel(for: FordF150()) 5.6

Slide 18

Slide 18 text

Massive generic improvements Primary associated type for protocols protocol Vehicle { associatedtype Kind } struct TeslaModel3: Vehicle { typealias Kind = Electric } struct FordF150: Vehicle { typealias Kind = Gasoline } func fillFuel(for vehicle: some Vehicle) But now you can add a primary associated type, which tidies everything up: fillFuel(for: TeslaModel3()) fillFuel(for: FordF150()) 5.7

Slide 19

Slide 19 text

Distributed actors Isolated and protects mutable state like a regular actor, but across multiple processes - for example, different devices or entirely different servers distributed actor RemotePlayer: GamePlayer { public distributed func makeMove() async -+ GameMove { /" async distributed work } } 5.7

Slide 20

Slide 20 text

@available(*, noasync) func someSynchronousThing() { /" Some async work } func otherAsyncFunc() async { someSynchronousThing() } @available(*, noasync) 5.7

Slide 21

Slide 21 text

Result Builders get buildPartialBlock func buildBlock(_ c0: C0, _ c1: C1) -+ TupleView<(C0, C1)> where C0: View, C1: View func buildBlock(_ c0: C0, _ c1: C1, _ c2: C2) -+ TupleView<(C0, C1, C2)> where C0: View, C1: View, C2: View func buildBlock(_ c0: C0, _ c1: C1, _ c2: C2, _ c3: C3) -+ TupleView<(C0, C1, C2, C3)> where C0: View, C1: View, C2: View, C3: View VStack { Text("1") Text("2") Text("3") Text("4") } Arity is limited to the number of generic overloads 5.6

Slide 23

Slide 23 text

More concurrency-related features swift-async-algorithms indicates Apple’s push towards async/await over other options (such as Combine) Plus, a lot of new tooling for concurrency debugging, such as a new Concurrency template for Instruments:

Slide 24

Slide 24 text

Apple pushing hard on SwiftUI for new development

Slide 25

Slide 25 text

Thanks! try! Swift DUB DUB 2022 ! Shai Mishali @freak4pc