towry
7/10/2017 - 2:29 AM

container.swift


// where clause in the extension declaration level.
extension Array where Element == Int {
  public func printSelf() {
    print("OK")
  }
}

extension Array where Element == String {
  public func printSelf() {
    print("not ok")
  }
}

let a = Array(["abc", "efg"])
a.printSelf()
let b = Array([1,2,3])
b.printSelf()
/// https://github.com/apple/swift-evolution/blob/master/proposals/0142-associated-types-constraints.md

protocol SubContainer: Container {
  associatedtype Item: Equatable
}

protocol Container {
  associatedtype Item
  // error: 'where' clause cannot be attached to an associated type declaration
  // error: type may not reference itself as a requirement
  associatedtype SubContainer: Container where SubContainer.Item == Item

  mutating func append(_ item: Item)
  var count: Int { get }
  subscript(i: Int) -> Item { get }
}


/// Element is the appropriate type to use
/// as the Item for this particular container.
/// Below swift 4, you can not use where clause in protocol with associatedtype.
/// but you can use where caluse in protocol extension before the body.
/// and where clause can not be attached to a non-generic declaration.
/// typealias can not be used in protocol, use it in protocol extension.
struct Stack<Element>: Container where Element: Equatable {
  typealias Item = Element // non-generic declaration
  typealias SubContainer = Stack<Element> // non-generic declaration

  var items = [Element]()

  mutating func push(_ item: Element) {
    items.append(item)
  }

  mutating func pop() -> Element {
    return items.removeLast()
  }

  mutating func append(_ item: Element) {
    self.push(item)
  }

  var count: Int {
    return items.count
  }

  subscript(i: Int) -> Element {
    return items[i]
  }
}

/// Use where clause.
extension Container where Item: Equatable {}

var s = Stack<Int>()