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

Make our Swift better in India

d_date
July 28, 2019

Make our Swift better in India

2019/07/28 SwiftIndia

d_date

July 28, 2019
Tweet

More Decks by d_date

Other Decks in Programming

Transcript

  1. Daiki Matsudate • Tokyo, Japan • iOS Developer from iOS

    4 • FOLIO -> ??? • Google Developer Expert for Firebase • Open API Generator Technical Committee • @d_date • Sushi
  2. static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] {

    var destination = [String: String]() for (key, nillableValue) in source { if let value: Any = nillableValue { destination[key] = "\(value)" } } return destination }
  3. static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] {

    return source.flatMap { $0 } // [(key: String, value: String)] }
  4. static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] {

    var destination = [String: String]() for (key, nillableValue) in source { if let value: Any = nillableValue { destination[key] = "\(value)" } } return destination }
  5. static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] {

    return source.reduce(into: [String: String](), { (result, x) in if let value = x.value { result[x.key] = "\(value)" } }) }
  6. static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] {

    return source.reduce(into: [String: String](), { (result, x) in if let value = x.value { result[x.key] = "\(value)" } }) } public func reduce<Result>(into initialResult: Result, _ updateAccumulatingResult: (inout Result, (key: Key, value: Value)) throws -> ()) rethrows -> Result
  7. static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] {

    return source.reduce(into: [String: String](), { (result, x) in if let value = x.value { result[x.key] = "\(value)" } }) } rejectNilHeaders(["a": "1", "b": nil, "c": "3"]) // ["a" : 1, "c" : 3]
  8. static func rejectNilHeaders(_ source: [String: Any?]) -> [String: String] {

    return source.reduce(into: [String: String](), { (result, x) in if let value = x.value { result[x.key] = "\(value)" } }) } ["a": "1", "b": nil, "c": “3”].xxx({ $0 }) // ["a" : 1, "c" : 3]
  9. map and flatMap in Collection let r = [1, 2,

    3].map { $0 * 2 } // [2, 4, 6] let r22 = [1, nil, 3].flatMap { $0 } // [1, 3]
  10. map and compactMap in Collection let r = [1, 2,

    3].map { $0 * 2 } // [2, 4, 6] let r22 = [1, nil, 3].compactMap { $0 } // [1, 3]
  11. ["a": "1", "b": nil, "c": “3”].compactMapValues({ $0 }) // ["a"

    : 1, "c" : 3] extension Dictionary { public func compactMapValues<T>(_ transform: (Value) throws -> T?) rethrows -> [Key: T] { return try self.reduce(into: [Key: T](), { (result, x) in if let value = try transform(x.value) { result[x.key] = value } }) } }
  12. extension Dictionary { public func compactMapValues<T>(_ transform: (Value) throws ->

    T?) rethrows -> [Key: T] { return try self.reduce(into: [Key: T](), { (result, x) in if let value = try transform(x.value) { result[x.key] = value } }) } }
  13. Proposal • Introduction • Motivation • Proposed Solution • Detailed

    Design • Source compatibility • Effect on ABI stability / API resilience • Alternative considered
  14. 4. Implement your idea /// Returns a new dictionary containing

    the keys of this dictionary with the /// values transformed by the given closure. /// - Parameter transform: A closure that transforms a value. `transform` /// accepts each value of the dictionary as its parameter and returns a /// transformed value of the same or of a different type. /// - Returns: A dictionary containing the keys and transformed values of /// this dictionary. @inlineable // FIXME(sil-serialize-all) public func compactMapValues<T>( _ transform: (Value) throws -> T? ) rethrows -> Dictionary<Key, T> { return try self.reduce(into: [Key: T](), { (result, x) in if let value = try transform(x.value) { result[x.key] = value } }) }
  15. 5. Test your implementation // RUN: %target-run-simple-swift // REQUIRES: executable_test

    // REQUIRES: objc_interop import Foundation import StdlibUnittest var tests = TestSuite("CompactMapValues") tests.test("DefaultReturnType") { var result = ["a": "1", "c": "3"].compactMapValues { $0 } expectType([String: String].self, &result) } tests.test("ExplicitTypeContext") { expectEqual(["a":"1","c":"3"], ["a":"1","b":nil,"c":"3"].compactMapValues({$0}) ) expectEqual(["a": 1, "b": 2], ["a":"1","b":"2", "c":"three"].compactMapValues(Int.init) ) } runAllTests()
  16. // RUN: %target-run-simple-swift // REQUIRES: executable_test // REQUIRES: objc_interop import

    Foundation import StdlibUnittest var tests = TestSuite("CompactMapValues") tests.test("DefaultReturnType") { var result = ["a": "1", "c": "3"].compactMapValues { $0 } expectType([String: String].self, &result) } tests.test("ExplicitTypeContext") { expectEqual(["a":"1","c":"3"], ["a":"1","b":nil,"c":"3"].compactMapValues({$0}) ) expectEqual(["a": 1, "b": 2], ["a":"1","b":"2", "c":"three"].compactMapValues(Int.init) ) } runAllTests() Import Write your test case 5. Test your implementation
  17. 6. Benchmark your changes (Optional) public let DictionaryCompactMapValues = [

    BenchmarkInfo(name: "DictionaryCompactMapValuesOfNilValue", runFunction: run_DictionaryCompactMapValuesOfNilValue, tags: [.validation, .api, .Dictionary]),] @inline(never) public func run_DictionaryCompactMapValuesOfNilValue(_ N: Int) { let size = 100 var dict = [Int: Int?](minimumCapacity: size) // Fill Dictionary for i in 1...size { if i % 2 == 0 { dict[i] = nil } else { dict[i] = i } } CheckResults(dict.count == size / 2) var refDict = [Int: Int]() for i in stride(from: 1, to: 100, by: 2) { refDict[i] = i } var newDict = [Int: Int]() for _ in 1...1000*N { newDict = dict.compactMapValues({$0}) if newDict != refDict { break } } CheckResults(newDict == refDict) }
  18. 6. Benchmark your changes (Optional) public let DictionaryCompactMapValues = [

    BenchmarkInfo(name: "DictionaryCompactMapValuesOfNilValue", runFunction: run_DictionaryCompactMapValuesOfNilValue, tags: [.validation, .api, .Dictionary]),] @inline(never) public func run_DictionaryCompactMapValuesOfNilValue(_ N: Int) { let size = 100 var dict = [Int: Int?](minimumCapacity: size) // Fill Dictionary for i in 1...size { if i % 2 == 0 { dict[i] = nil } else { dict[i] = i } } CheckResults(dict.count == size / 2) var refDict = [Int: Int]() for i in stride(from: 1, to: 100, by: 2) { refDict[i] = i } var newDict = [Int: Int]() for _ in 1...1000*N { newDict = dict.compactMapValues({$0}) if newDict != refDict { break } } CheckResults(newDict == refDict) } Specify your benchmark Prepare the data Check compactMapValues work
  19. import Foundation import UIKit let label = UILabel() let attributes:

    [NSAttributedString.Key: Any] = [.font: UIFont(name: "Menlo", size: 14)] let attributedText = NSAttributedString(string: “Great conference I love”, attributes: attributes) label.attributedText = attributedText
  20. import Foundation import UIKit let label = UILabel() let attributes:

    [NSAttributedString.Key: Any] = [.font: UIFont(name: "Menlo", size: 14)] let attributedText = NSAttributedString(string: “Great conference I love”, attributes: attributes) label.attributedText = attributedText
  21. import Foundation import UIKit let label = UILabel() let attributes:

    [NSAttributedString.Key: Any] = [.font: UIFont(name: "Menlo", size: 14)].compactMapValues {$0} let attributedText = NSAttributedString(string: "Great conference I love", attributes: attributes) label.attributedText = attributedText
  22. Recap 0. Get advice from local community 1. Post your

    idea to forum.swift.org 2. Make proposal to Swift-evolution 3. Build your environment 4. Implement your idea 5. Test your implementation 6. Benchmark your changes (Optional) 7. Waiting to starting evolution process