[Pitch] Allow use associated type outside of its protocol


(frogcjn) #1

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:

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:

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:

album.sectionedMediaItemInfos.itemsCount

That looks good.

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

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:

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.

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


(Xiaodi Wu) #2

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:

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:

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:

album.sectionedMediaItemInfos.itemsCount

That looks good.

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

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

Sorry, I'm reading this quickly, but I'm confused as to why you're not
writing `var items: [Element.SectionItemType]`. That seems to be what you
want, no? `SectionProtocol.SectionItemType` has no constraints and, even if
the grammar allowed you to write it, would have to be equivalent to `Any`.

This doesn’t work. It reported as "Cannot use associated type

···

On Sun, Feb 19, 2017 at 5:04 PM, 曹剑楠 via swift-evolution < swift-evolution@swift.org> wrote:

'SectionItemType' outside of its protocol"

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

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.

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(frogcjn) #3

OK, my fault. That solved the problem.

var items: [Element.SectionItemType]

I should use this.

How about to allow using generic type Section directly instead of declare a protocol

public extension Array where Element == Section {
    
    var itemsCount: Int {
        return reduce(0) { (result, section) in result + section.items.count }
    }
    
    var items: [Element.SectionItemType] {
        return self.flatMap { $0.items }
    }
}
···

在 2017年2月20日,上午7:14,Xiaodi Wu <xiaodi.wu@gmail.com> 写道:

On Sun, Feb 19, 2017 at 5:04 PM, 曹剑楠 via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
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:

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:

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:

album.sectionedMediaItemInfos.itemsCount

That looks good.

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

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

Sorry, I'm reading this quickly, but I'm confused as to why you're not writing `var items: [Element.SectionItemType]`. That seems to be what you want, no? `SectionProtocol.SectionItemType` has no constraints and, even if the grammar allowed you to write it, would have to be equivalent to `Any`.

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:

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.

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(frogcjn) #4

Sorry about my typo:

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 extension Array where Element == Sectioned {
    
    var itemsCount: Int {
        return reduce(0) { (result, section) in result + section.items.count }
    }
    
    var items: [Element.Item] {
        return self.flatMap { $0.items }
    }
}

Allow extension Array with strict its Element with a struct type (may be generic) is highly wanted feature.

···

在 2017年2月20日,上午7:28,曹剑楠 <frogcjn@163.com> 写道:

OK, my fault. That solved the problem.

var items: [Element.SectionItemType]

I should use this.

How about to allow using generic type Section directly instead of declare a protocol

public extension Array where Element == Section {
   
    var itemsCount: Int {
        return reduce(0) { (result, section) in result + section.items.count }
    }
   
    var items: [Element.SectionItemType] {
        return self.flatMap { $0.items }
    }
}

在 2017年2月20日,上午7:14,Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> 写道:

On Sun, Feb 19, 2017 at 5:04 PM, 曹剑楠 via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
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:

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:

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:

album.sectionedMediaItemInfos.itemsCount

That looks good.

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

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

Sorry, I'm reading this quickly, but I'm confused as to why you're not writing `var items: [Element.SectionItemType]`. That seems to be what you want, no? `SectionProtocol.SectionItemType` has no constraints and, even if the grammar allowed you to write it, would have to be equivalent to `Any`.

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:

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.

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution


(Xiaodi Wu) #5

That is a new feature in Swift 3.1.

···

On Sun, Feb 19, 2017 at 5:32 PM, 曹剑楠 <frogcjn@163.com> wrote:

Sorry about my typo:

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 extension Array where Element == Sectioned {

    var itemsCount: Int {
        return reduce(0) { (result, section) in result +
section.items.count }
    }

    var items: [Element.Item] {
        return self.flatMap { $0.items }
    }
}

Allow extension Array with strict its Element with a struct type (may be
generic) is highly wanted feature.

在 2017年2月20日,上午7:28,曹剑楠 <frogcjn@163.com> 写道:

OK, my fault. That solved the problem.

var items: [Element.SectionItemType]

I should use this.

How about to allow using generic type Section directly instead of declare
a protocol

public extension Array where Element == Section {

    var itemsCount: Int {
        return reduce(0) { (result, section) in result +
section.items.count }
    }

    var items: [Element.SectionItemType] {
        return self.flatMap { $0.items }
    }
}

在 2017年2月20日,上午7:14,Xiaodi Wu <xiaodi.wu@gmail.com> 写道:

On Sun, Feb 19, 2017 at 5:04 PM, 曹剑楠 via swift-evolution < > swift-evolution@swift.org> wrote:

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:

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:

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:

album.sectionedMediaItemInfos.itemsCount

That looks good.

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

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

Sorry, I'm reading this quickly, but I'm confused as to why you're not
writing `var items: [Element.SectionItemType]`. That seems to be what you
want, no? `SectionProtocol.SectionItemType` has no constraints and, even
if the grammar allowed you to write it, would have to be equivalent to
`Any`.

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:

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.

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution


(frogcjn) #6

Thanks! Waiting for the new version.

···

在 2017年2月20日,上午7:42,Xiaodi Wu <xiaodi.wu@gmail.com> 写道:

That is a new feature in Swift 3.1.

On Sun, Feb 19, 2017 at 5:32 PM, 曹剑楠 <frogcjn@163.com <mailto:frogcjn@163.com>> wrote:
Sorry about my typo:

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 extension Array where Element == Sectioned {
    
    var itemsCount: Int {
        return reduce(0) { (result, section) in result + section.items.count }
    }
    
    var items: [Element.Item] {
        return self.flatMap { $0.items }
    }
}

Allow extension Array with strict its Element with a struct type (may be generic) is highly wanted feature.

在 2017年2月20日,上午7:28,曹剑楠 <frogcjn@163.com <mailto:frogcjn@163.com>> 写道:

OK, my fault. That solved the problem.

var items: [Element.SectionItemType]

I should use this.

How about to allow using generic type Section directly instead of declare a protocol

public extension Array where Element == Section {
   
    var itemsCount: Int {
        return reduce(0) { (result, section) in result + section.items.count }
    }
   
    var items: [Element.SectionItemType] {
        return self.flatMap { $0.items }
    }
}

在 2017年2月20日,上午7:14,Xiaodi Wu <xiaodi.wu@gmail.com <mailto:xiaodi.wu@gmail.com>> 写道:

On Sun, Feb 19, 2017 at 5:04 PM, 曹剑楠 via swift-evolution <swift-evolution@swift.org <mailto:swift-evolution@swift.org>> wrote:
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:

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:

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:

album.sectionedMediaItemInfos.itemsCount

That looks good.

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

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

Sorry, I'm reading this quickly, but I'm confused as to why you're not writing `var items: [Element.SectionItemType]`. That seems to be what you want, no? `SectionProtocol.SectionItemType` has no constraints and, even if the grammar allowed you to write it, would have to be equivalent to `Any`.

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:

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.

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

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org <mailto:swift-evolution@swift.org>
https://lists.swift.org/mailman/listinfo/swift-evolution