[swift-evolution] [Pitch] Allow use associated type outside of its protocol

曹剑楠 frogcjn at 163.com
Sun Feb 19 17:04:15 CST 2017


Hi All,

I’m coding for section like data structure. 
For example:

I have an Album struct, which has many MediaItems.
It has a sectioned property called "sectionedMediaItemInfos", which is an array of sections.
Each section represents for a disc, and has an "items" array contains all MedaItems in that disc.

The define code is like:

```Swift
public struct Album {
    public let sectionedMediaItemInfos: [Sectioned<MediaItemInfo>]?
}

public struct Sectioned<Item> : SectionProtocol {
    public let title: String?
    public let items: [Item]
    
    public init() {
        items = []
        title = nil
    }
}

public protocol SectionProtocol {
    associatedtype SectionItemType
    var items: [SectionItemType] { get }
}
```

Now I want to define some extra properties for sections array, like
"sectionMediaItemInfos"."itemsCount" that count all items in each sections.
So I can write that extension:

```Swift
public extension Array where Element : SectionProtocol {
    
    var itemsCount: Int {
        return reduce(0) { (result, section) in result + section.items.count }
    }

}
```

So I can get my itemsCount with code like:

```Swift
album.sectionedMediaItemInfos.itemsCount
```

That looks good.

Then I want to define code to return all items in this sectioned property.


```Swift
public extension Array where Element : SectionProtocol {
    var items: [SectionProtocol.SectionItemType] {
        return .flatMap { $0.items }
    }
}
```

This doesn’t work. It reported as "Cannot use associated type 'SectionItemType' outside of its protocol"

The only way to achieve my goals is to untyped the extended "items" property:

```Swift
public extension Array where Element : SectionProtocol {
    var items: [Any] {
        return self.flatMap { $0.items }
    }
}
```

Which is not perfect for this case.


So in this special case, I think allow use associated type outside of its protocol is necessary.

And we may allow define protocol with generic type. That would be more convenient.


```Swift
public struct Album {
    public let sectionedMediaItemInfos: [Sectioned<MediaItemInfo>]?
}


public struct Sectioned<Item> : SectionProtocol {
    public let title: String?
    public let items: [Item]
    
    public init() {
        items = []
        title = nil
    }
}

public protocol SectionProtocol<SectionItemType> {
    var items: [SectionItemType] { get }
}


public extension Array where Element : SectionProtocol {
    var items: [Element.SectionItemType] {
        return self.flatMap { $0.items }
    }
}

```

Thank all!

Jiannan



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170220/b4f6cc35/attachment.html>


More information about the swift-evolution mailing list