Generic, subscript and protocol?

I am using a data source -- think UITableViewDataSource -- that caches the real data for dynamic filtering purposes, but in such a way that client code only has to rely on the existence of a `count` property and a `subscript` element accessor.


But, as of Swift 2.x, Xcode 7.2, this fails to compile:


protocol Iterable {
    typealias ItemType
    var count: Int { get }
    subscript(index: Int) -> ItemType
}


=> .../Iterable.swift:20:38: Expected '{' for subscripting

If I cannot use protocols, maybe, sadly, a class will do?


class Iterable<Element> {
    var count:Int = 0
    subscript(index:Int) -> Element
}


=> .../Iterable.swift:26:36: Expected '{' for subscripting


Hmmm ...


Assuming I were able to define such an Iterable(*) in some way, the intended use was something along the lines


class MyIterable<Element> : Iterable {
   ...

   var items:[Element] = []
   var cache:[Element] = []

    ...
   func filter() {
        ...
       cache = ...
   }
   ...
    var count:Int {
        return cache.count
    }
    ...
    subscript(index:Int) -> Element {
        return cache[index]
    }
    ...
}


and at the use site:


func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return myIterable.count
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = self.dequeueReusableCellWithIdentifier(Parameters.productionCellId, forIndexPath: indexPath)
    if indexPath.row >= myIterable.count {
        return cell
    }
    let item = myIterable[indexPath.row]
    ...
    return cell
}


How could I achieve this?


(*) the `Indexable` name is already reserved by the standard Swift library, for a related, but different purpose.

Answered by QuinceyMorris in 96224022

The error message says: "Expected '{' for subscripting". That is to say, it expects this in the protocol:


subscript(index: Int) -> ItemType {...


which should be a clue that the correct form is:


subscript(index: Int) -> ItemType { get } // or
subscript(index: Int) -> ItemType { get set }


depending whether you want a setter too.

Accepted Answer

The error message says: "Expected '{' for subscripting". That is to say, it expects this in the protocol:


subscript(index: Int) -> ItemType {...


which should be a clue that the correct form is:


subscript(index: Int) -> ItemType { get } // or
subscript(index: Int) -> ItemType { get set }


depending whether you want a setter too.

which should be a clue that the correct form is:

Indeed. IMO the compiler should give a better diagnostic here. I’ve filed a bug (r. 23952125) to that effect.

Share and Enjoy

Quinn "The Eskimo!"
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

DTS will close for the winter holidays at the end of business on Wed, 23 Dec 2015 and re-open on Mon, 4 Jan 2016.

Thanks! This is now fixed in what will become Swift 2.2:

https://github.com/apple/swift/commit/c5acfa1849fc5fc836e87217f4fdc6eec6eab741


-Chris

Generic, subscript and protocol?
 
 
Q