Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Swift 5.7 in 5(-ish) minutes

Swift 5.7 in 5(-ish) minutes

This is a lightning talk I gave at try! Swift World - WWDC 2022 Edition

Shai Mishali

June 10, 2022
Tweet

More Decks by Shai Mishali

Other Decks in Technology

Transcript

  1. Shorthand optional unwrapping if let extremelyLongOptionalVariable /" Do something with

    `extremelyLongOptionalVariable` } = extremelyLongOptionalVariable { 5.6
  2. 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
  3. 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
  4. 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
  5. First-class Regular Expression let regex = #/ #' (?<firstHex>[A-Fa-f0-9]{2}) (?<secondHex>[A-Fa-f0-9]{2})

    (?<thirdHex>[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
  6. First-class Regular Expression let regex = #/ #' (?<firstHex>[A-Fa-f0-9]{2}) (?<secondHex>[A-Fa-f0-9]{2})

    (?<thirdHex>[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
  7. First-class Regular Expression let regex = #/ #' (?<firstHex>[A-Fa-f0-9]{2}) (?<secondHex>[A-Fa-f0-9]{2})

    (?<thirdHex>[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
  8. 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
  9. 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
  10. async/await in top-level code You can run concurrency-related command right

    at your main.swift: try await someLongRunningCommand() 5.7
  11. Concrete-typed default values for generic expressions func pickElement<T: Collection>(from elements:

    T = 1..%100) -+ T.Element? { elements.randomElement() } pickElement() /" 27 pickElement(from: ["A", "B", “C”]) /" B 5.7 func pickElement<T: Collection>(from elements: T) -+ T.Element { elements.randomElement()! } pickElement(from: ["A", "B", “C"]) /" B 5.6
  12. 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<V: Vehicle>(for vehicle: V) func fillFuel(for vehicle: some Vehicle) 5.6 5.7
  13. 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
  14. 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
  15. 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
  16. 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<V: Vehicle>(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
  17. Massive generic improvements Primary associated type for protocols protocol Vehicle<Kind>

    { associatedtype Kind } struct TeslaModel3: Vehicle { typealias Kind = Electric } struct FordF150: Vehicle { typealias Kind = Gasoline } func fillFuel(for vehicle: some Vehicle<Gasoline>) But now you can add a primary associated type, which tidies everything up: fillFuel(for: TeslaModel3()) fillFuel(for: FordF150()) 5.7
  18. 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
  19. @available(*, noasync) func someSynchronousThing() { /" Some async work }

    func otherAsyncFunc() async { someSynchronousThing() } @available(*, noasync) 5.7
  20. Result Builders get buildPartialBlock func buildBlock<C0, C1>(_ c0: C0, _

    c1: C1) -+ TupleView<(C0, C1)> where C0: View, C1: View func buildBlock<C0, C1, C2>(_ c0: C0, _ c1: C1, _ c2: C2) -+ TupleView<(C0, C1, C2)> where C0: View, C1: View, C2: View func buildBlock<C0, C1, C2, C3>(_ 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
  21. Result Builders get buildPartialBlock func buildPartialBlock<A>(first content: A) -+ A

    func buildPartialBlock<A, B>(accumulated: A, next: B) -+ SomeResult<A, B> These two new Result Builder methods let you build a result accumulatively: VStack { Text("1") Text("2") Text("3") Text("4") } let step0 = buildPartialBlock(first: Text("1")) let step1 = buildPartialBlock(accumulated: step0, next: Text("2")) let step2 = buildPartialBlock(accumulated: step1, next: Text("3")) let step3 = buildPartialBlock(accumulated: step2, next: Text(“4") /" and on ..- So, if (when) SwiftUI implements these new methods, it would be able to potentially expand to unlimited amount of members: 5.7
  22. 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: