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

Swifty?

Sponsored · SiteGround - Reliable hosting with speed, security, and support you can count on.

 Swifty?

Presented at Swift London.

Swift is young, and we're still figuring out what Swifty code looks like. I'll take a look at emerging idioms and patterns, and how Swift 3 will mix things up (again).

Avatar for Dan Cutting

Dan Cutting

July 05, 2016
Tweet

More Decks by Dan Cutting

Other Decks in Programming

Transcript

  1. enum Encrypted {} // Phantom types! enum Decrypted {} func

    transmit(message: Secret<Encrypted>) { // ... } struct Secret<T> { let value: String }
  2. Cannot convert value of type 'Secret<Decrypted>' to expected argument type

    'Secret<Encrypted>' func getSpyReport() -> Secret<Decrypted> { return Secret(value: "!") } let report = getSpyReport() transmit(message: report)
  3. func encrypt(message: Secret<Decrypted>) -> Secret<Encrypted> { let encrypted = rot13(message:

    message.value) return Secret(value: encrypted) } let report = getSpyReport() let encrypted = encrypt(message: report) transmit(message: encrypted)
  4. class Warren { enum Mick { struct Jim { static

    let rock = true } } } Warren.Mick.Jim.rock
  5. enum MyProject { struct Array { // ... } }

    let myArray = MyProject.Array()
  6. enum Components { enum List {} enum Search {} enum

    Detail {} } extension Components.List { class Service { // ... } } let listService = Components.List.Service()
  7. mixin CanMove { var position = CGPoint.zero var speed =

    CGVector.zero func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } } struct Player: CanMove, HasHealth {} struct Enemy: CanMove, HasMagic {}
  8. struct CanMoveMixin { var position = CGPoint.zero var speed =

    CGVector.zero mutating func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } } mixin CanMove { var position = CGPoint.zero var speed = CGVector.zero func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } }
  9. protocol CanMove { mutating func move(for timeSlice: CGFloat) } mixin

    CanMove { var position = CGPoint.zero var speed = CGVector.zero func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } }
  10. struct Player: CanMove { var canMoveMixin = CanMoveMixin() mutating func

    move(for timeSlice: CGFloat) { canMoveMixin.move(for: timeSlice) } }
  11. struct Enemy: CanMove { var canMoveMixin = CanMoveMixin() mutating func

    move(for timeSlice: CGFloat) { canMoveMixin.move(for: timeSlice) } }
  12. protocol CanMove { mutating func move(for timeSlice: CGFloat) } var

    canMoveMixin: CanMoveMixin { get set } extension CanMove { mutating func move(for timeSlice: CGFloat) { canMoveMixin.move(for: timeSlice) } }
  13. struct Player: CanMove, HasHealth { var canMoveMixin = CanMoveMixin() var

    hasHealthMixin = HasHealthMixin() } struct Enemy: CanMove, HasMagic { var canMoveMixin = CanMoveMixin() var hasMagicMixin = HasMagicMixin() } struct Player: CanMove, HasHealth {} struct Enemy: CanMove, HasMagic {}
  14. • SE-0007: Remove C-style for-loops with conditions and incrementers •

    SE-0016: Adding initializers to Int and UInt to convert from UnsafePointer and UnsafeMutablePointer • SE-0019: Swift Testing • SE-0023: API Design Guidelines • SE-0028: Modernizing Swift's Debugging Identifiers (__FILE__, etc) • SE-0029: Remove implicit tuple splat behavior from function applications • SE-0031: Adjusting inout Declarations for Type Decoration • SE-0034: Disambiguating Line Control Statements from Debugging Identifiers • SE-0037: Clarify interaction between comments & operators • SE-0039: Modernizing Playground Literals • SE-0040: Replacing Equal Signs with Colons For Attribute Arguments • SE-0043: Declare variables in 'case' labels with multiple patterns • SE-0046: Establish consistent label behavior across all parameters including first labels • SE-0049: Move @noescape and @autoclosure to be type attributes • SE-0053: Remove explicit use of let from Function Parameters • SE-0054: Abolish ImplicitlyUnwrappedOptional type • SE-0055: Make unsafe pointer nullability explicit using Optional • SE-0059: Update API Naming Guidelines and Rewrite Set APIs Accordingly • SE-0061: Add Generic Result and Error Handling to autoreleasepool() • SE-0065: A New Model For Collections and Indices • SE-0069: Mutability and Foundation Value Types • SE-0070: Make Optional Requirements Objective-C-only • SE-0071: Allow (most) keywords in member references • SE-0072: Fully eliminate implicit bridging conversions from Swift • SE-0025: Scoped Access Level • SE-0032: Add find method to SequenceType • SE-0033: Import Objective-C Constants as Swift Types • SE-0035: Limiting inout capture to @noescape contexts • SE-0036: Requiring Leading Dot Prefixes for Enum Instance Member Impleme • SE-0038: Package Manager C Language Target Support • SE-0042: Flattening the function type of unapplied method references • SE-0044: Import as Member • SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib • SE-0047: Defaulting non-Void functions so they warn on unused results • SE-0048: Generic Type Aliases • SE-0052: Change IteratorType post-nil guarantee • SE-0057: Importing Objective-C Lightweight Generics • SE-0062: Referencing Objective-C key-paths • SE-0063: SwiftPM System Module Search Paths • SE-0064: Referencing the Objective-C selector of property getters and setters • SE-0066: Standardize function type argument syntax to require parentheses • SE-0067: Enhanced Floating Point Protocols • SE-0068: Expanding Swift Self to class members and value types
  15. public class Counter { private var value: Int = 0

    public func increment() { value += 1 } } let counter = Counter() counter.increment() counter.value = 99 Scoped Access
  16. func apply(value: Int, f: @noescape (Int) -> (Int)) -> Int

    { return f(value) }. let _ = apply(value: 7) { $0 * 2 }. @noescape
  17. func apply(value: Int, f: (Int) -> (Int)) -> Int {

    return f(value) }. let _ = apply(value: 7) { $0 * 2 }. @noescape
  18. protocol Drama {} protocol Comedy {} struct BreakfastClub: Drama, Comedy

    {} let movie: Drama & Comedy = BreakfastClub() let movie: protocol<Drama, Comedy> = BreakfastClub() func watch<T: Drama & Comedy>(dramedy: T) { // ... } Protocols
  19. for loops! for (var i = 0; i < 10;

    i++) { print(i) } for i in (0..<10) { print(i) }
  20. for x in sequence(first: 1, next: { $0 * 2

    }) { print(x) } .prefix(4)
  21. struct Fib { var current: Int var next: Int }

    let f = Fib(current: 0, next: 1) let s = sequence(state: f) { (f: inout Fib) -> Int? in return f.current } defer { } let sum = f.current + f.next f.current = f.next f.next = sum