Swift Style

06609d73ad2165c4aafcf65a1ddb9563?s=47 Greg Heo
January 10, 2016

Swift Style

Presented at @Swift conference, Beijing, 10 January 2016.

06609d73ad2165c4aafcf65a1ddb9563?s=128

Greg Heo

January 10, 2016
Tweet

Transcript

  1. Swift Style @gregheo

  2. Style?

  3. None
  4. None
  5. for _ in 0..<indent { print(" ", terminator: "", toStream:

    &targetStream) }; let count = mirror.count; let bullet = count == 0 ? “-" : maxDepth <= 0 ? "▹" : “▿”; print("\(bullet) ", terminator: "", toStream: &targetStream) if let nam = name { print("\(nam): ", terminator: "", toStream: &targetStream); } print(mirror.summary, terminator: "", toStream: &targetStream); if let id = mirror.objectIdentifier { if let previous = visitedItems[id] { print(" #\(previous)", toStream: &targetStream); return; } let identifier = visitedItems.count; visitedItems[id] = identifier; print(" #\ (identifier)", terminator: "", toStream: &targetStream); }
  6. for _ in 0..<indent { print(" ", terminator: "", toStream:

    &targetStream) } let count = mirror.count let bullet = count == 0 ? "-" : maxDepth <= 0 ? "▹" : "▿" print("\(bullet) ", terminator: "", toStream: &targetStream) if let nam = name { print("\(nam): ", terminator: "", toStream: &targetStream) } print(mirror.summary, terminator: "", toStream: &targetStream) if let id = mirror.objectIdentifier { if let previous = visitedItems[id] { print(" #\(previous)", toStream: &targetStream) return } let identifier = visitedItems.count visitedItems[id] = identifier print(" #\(identifier)", terminator: "", toStream: &targetStream) }
  7. None
  8. MOV AX, SI MOV CX, BX DEC CX @OUTER_LOOP: MOV

    BX, CX MOV SI, AX MOV DI, AX INC DI @INNER_LOOP: MOV DL, [SI] CMP DL, [DI] JNG @SKIP_EXCHANGE XCHG DL, [DI] MOV [SI], DL @SKIP_EXCHANGE: INC SI INC DI DEC BX JNZ @INNER_LOOP LOOP @OUTER_LOOP MOV AX, SI ; set AX=SI MOV CX, BX ; set CX=BX DEC CX ; set CX=CX-1 @OUTER_LOOP: ; loop label MOV BX, CX ; set BX=CX MOV SI, AX ; set SI=AX MOV DI, AX ; set DI=AX INC DI ; set DI=DI+1 @INNER_LOOP: ; loop label MOV DL, [SI] ; set DL=[SI] CMP DL, [DI] ; compare DL with [DI] JNG @SKIP_EXCHANGE ; jump to label @SKIP_EXCHANGE if DL<[DI] XCHG DL, [DI] ; set DL=[DI], [DI]=DL MOV [SI], DL ; set [SI]=DL @SKIP_EXCHANGE: ; jump label INC SI ; set SI=SI+1 INC DI ; set DI=DI+1 DEC BX ; set BX=BX-1 JNZ @INNER_LOOP ; jump to label @INNER_LOOP if BX!=0 LOOP @OUTER_LOOP
  9. MOV AX, SI ; set AX=SI MOV CX, BX ;

    set CX=BX DEC CX ; set CX=CX-1 @OUTER_LOOP: ; loop label MOV BX, CX ; set BX=CX MOV SI, AX ; set SI=AX MOV DI, AX ; set DI=AX INC DI ; set DI=DI+1 @INNER_LOOP: ; loop label MOV DL, [SI] ; set DL=[SI] CMP DL, [DI] ; compare DL with [DI] JNG @SKIP_EXCHANGE ; jump to label @SKIP_EXCHANGE if DL<[DI] XCHG DL, [DI] ; set DL=[DI], [DI]=DL MOV [SI], DL ; set [SI]=DL @SKIP_EXCHANGE: ; jump label INC SI ; set SI=SI+1 INC DI ; set DI=DI+1 DEC BX ; set BX=BX-1 JNZ @INNER_LOOP ; jump to label @INNER_LOOP if BX!=0 LOOP @OUTER_LOOP SORTING ALGORITHM
  10. – Structure and Interpretation of Computer Programs “Programs must be

    written for people to read, and only incidentally for machines to execute.”
  11. – Refactoring “Good programmers write code that humans can understand”

  12. for _ in 0..<indent { print(" ", terminator: "", toStream:

    &targetStream) }; let count = mirror.count; let bullet = count == 0 ? “-" : maxDepth <= 0 ? "▹" : “▿”; print("\(bullet) ", terminator: "", toStream: &targetStream) if let nam = name { print("\(nam): ", terminator: "", toStream: &targetStream); } print(mirror.summary, terminator: "", toStream: &targetStream); if let id = mirror.objectIdentifier { if let previous = visitedItems[id] { print(" #\(previous)", toStream: &targetStream); return; } let identifier = visitedItems.count; visitedItems[id] = identifier; print(" #\ (identifier)", terminator: "", toStream: &targetStream); }
  13. Concise Code

  14. [self beginTaskWithName:@"MyTask" completion:^{ NSLog(@"The task is complete"); }];

  15. self.beginTaskWithName("MyTask", completion: { print("The task is complete") })

  16. beginTaskWithName("MyTask", completion: { print("The task is complete") })

  17. beginTaskWithName("MyTask") { print("The task is complete") }

  18. beginTaskWithName("MyTask") { print("The task is complete") } [self beginTaskWithName:@"MyTask" completion:^{

    NSLog(@"The task is complete"); }];
  19. Concise Code

  20. None
  21. None
  22. •Value types •Protocols •Safety

  23. Value Types: Immutability

  24. NSArray NSData NSDictionary NSIndexSet NSSet NSString

  25. NSArray NSData NSDictionary NSIndexSet NSSet NSString NSMutableArray NSMutableData NSMutableDictionary NSMutableIndexSet

    NSMutableSet NSMutableString
  26. let var

  27. state! function inputs outputs

  28. Functional Programming

  29. Concurrency

  30. None
  31. Value Types: Immutability

  32. Value Types: Enumerations

  33. 0 30 60 90 Structs Classes Enums

  34. typedef NS_ENUM(NSInteger, TransportMode) { TransportModeAirplane, TransportModeBoat, TransportModeTruck };

  35. enum TransportMode { case Airplane case Boat case Truck }

  36. enum TransportMode { case Airplane case Boat case Truck }

    func emojiForTransportMode(mode: TransportMode) -> String { switch mode { case .Airplane: return "✈" case .Boat: return "⛵" case .Truck: return "" } }
  37. enum TransportMode { case Airplane case Boat case Truck func

    emojiRepresentation() -> String { switch self { case .Airplane: return "✈" case .Boat: return "⛵" case .Truck: return "" } } }
  38. enum TransportMode { case Airplane case Boat case Truck var

    emojiRepresentation: String { switch self { case .Airplane: return "✈" case .Boat: return "⛵" case .Truck: return "" } } }
  39. enum TransportMode: String { case Airplane = "✈" case Boat

    = "⛵" case Truck = "" } let t = TransportMode.Airplane t.rawValue // "✈"
  40. enum TransportMode: String { case Airplane = "✈" case Boat

    = "⛵" case Truck = ""
 case Rocket = "✈" }
  41. • Well-defined set of values • Segues • Asset catalog

    items Enumeration Uses
  42. • Computed properties • Methods • Raw values • Associated

    values Enumerations
  43. Protocols

  44. struct Sentence { let sentence: String init(_ sentence: String) {

    self.sentence = sentence } // ... } let mySentence = Sentence("Hello there")
  45. Value Type Behavior mySentence == otherSentence mySentence >= otherSentence print("\(mySentence)")

  46. struct Sentence { let sentence: String init(_ sentence: String) {

    self.sentence = sentence } // ... }
  47. extension Sentence: Equatable { } func ==(lhs: Sentence, rhs: Sentence)

    -> Bool { return lhs.sentence == rhs.sentence } mySentence == otherSentence
  48. extension Sentence: Comparable { } func <(lhs: Sentence, rhs: Sentence)

    -> Bool { return lhs.sentence < rhs.sentence } mySentence >= otherSentence
  49. print("\(mySentence)") Sentence(sentence: "Hello there") ↪

  50. extension Sentence: CustomStringConvertible { var description: String { return sentence

    } } print("\(mySentence)") Hello there ↪
  51. More Value Type Behavior dictionary[mySentence] = "value" let sentence =

    Sentence("Hello there") let sentence: Sentence = "Hello there" for word in mySentence { ... }
  52. extension Sentence: StringLiteralConvertible { // more code here!
 init(stringLiteral value:

    StringLiteralType) { self.sentence = value } } let otherSentence: Sentence = "Hello there"
  53. extension Sentence: Hashable { var hashValue: Int { return sentence.hashValue

    } } dictionary[mySentence] = "value" set.insert(mySentence)
  54. extension Sentence: SequenceType { func generate() -> SentenceGenerator {
 let

    words =
 sentence.componentsSeparatedByString(" ") return SentenceGenerator(words: words) } }
  55. struct SentenceGenerator: GeneratorType { let words: [String]
 var index =

    0
 } mutating func next() -> String? { if index < words.count { let thisIndex = index index += 1 return words[thisIndex] } else { return nil } }
  56. for word in mySentence { print("Word: \(word)") } Word: Hello

    Word: world
  57. Value Type Behavior • Equality • Comparison • Printing •

    Hashing • String conversion • Iteration == != > < <= >= print Set/dict “…” for x in …
  58. None
  59. Undefined Behavior

  60. Optionals?!

  61. !

  62. ? ?? if-let guard

  63. func decode() { if let x = input.next() { if

    _fastPath((x >> 11) != 0b1101_1) { return .Result(UnicodeScalar(x)) } else { return .Error } } return .EmptyInput } ✅ ❌
  64. guard let x = input.next() else
 { return .EmptyInput }

    if _fastPath((x >> 11) != 0b1101_1) { return .Result(UnicodeScalar(x)) } else { return .Error } ❌
  65. Preconditions & Assertions

  66. Assertions “internal sanity checks that are active during testing but

    do not impact performance of shipping code”
  67. Preconditions “Check a necessary condition for making forward progress.”

  68. Preconditions precondition(index >= 0,
 "vector index out of range") precondition(ablMemory

    != nil, "failed to allocate memory")
  69. fatalError() “Unconditionally stop execution.”

  70. Debug Release assert ✔ precondition ✔ ✔ fatalError() ✔ ✔

  71. •Value types •Protocols •Safety

  72. None
  73. None