Fast array expansion with common elements

I use Swift 3.1 and have some general structure:

struct Section<InfoT: Equatable, ItemsT: Equatable> {
    let info: InfoT?
    let items: [ItemsT]
}

And you want to expand the array using a custom method for elements of this generic type:

extension Array where Element == Section<Equatable, Equatable> {
    // Just dummy example function:
    func debugDummy() {
        for section in self {
            let info = section.info
            print("section info: \(info).")
            for item in section.items {
                print("item: \(item).")
            }
        }
    }
}

This gives me compilation errors:

error: using 'Equatable' as a concrete type conforming to protocol 'Equatable' is not supported
extension Array where Element == Section<Equatable, Equatable> {
                                 ^

error: GenericsListPlayground.playground:6:24: error: value of type 'Element' has no member 'info'
            let info = section.info
                       ^~~~~~~ ~~~~

error: GenericsListPlayground.playground:8:25: error: value of type 'Element' has no member 'items'
            for item in section.items {
                        ^~~~~~~ ~~~~~

How to declare such an extension? I tried several options for declaring this extension, for example:

extension Array where Element == Section (no arguments)

gives:

error: reference to generic type 'Section' requires arguments in <...>

etc ... none of them wants to compile.

+6
source share
2 answers

Try the following:

import Foundation

protocol Section {
    associatedtype InfoT: Equatable
    associatedtype ItemsT: Equatable
    var info: InfoT? { get }
    var items: [ItemsT] { get }
}

extension Array where Element: Section {
    // Just dummy example function:
    func debugDummy() {
        for section in self {
            let info = section.info
            print("section info: \(String(describing: info)).")
            for item in section.items {
                print("item: \(item).")
            }
        }
    }
}
+6
source

Derived from @Eppilo answer:

While the partition protocol is good, it is important to keep in mind the various ways to implement it.

, : Swift 3.1 :)

protocol Section {
    associatedtype InfoType: Equatable
    associatedtype ItemsType: Equatable
    var info: InfoType? { get set }
    var items: [ItemsType] { get set }
}

// This struct will try to infer the types for info and items when instantiating an object, any type that conforms to Equatable can be used while instantiating.
struct InferredSection<Info: Equatable, Items: Equatable> : Section {
    var info: Info?
    var items: [Items]
}

// This struct has explicit types, which means you can ONLY instantiate an object from this by using the specified types within the struct.
struct ExplicitSection : Section {

    typealias InfoType = String
    typealias ItemsType = Int

    var info: InfoType?
    var items: [ItemsType]
}

extension Array where Element: Section  {
    // Just dummy example function:
    func debugDummy() {
        for section in self {
            let info = section.info
            print("section info: \(String(describing: info)).")
            for item in section.items {
                print("item: \(item).")
            }
        }
    }
}

let explicit = ExplicitSection(info: "This section has explicit set types", items: [13, 37])
let inferred = InferredSection(info: "This section has inferred types", items: ["Foo", "Bar"])

let explicitTypeArray = [explicit, explicit]
let inferredTypeArray = [inferred, inferred]

explicitTypeArray.debugDummy()
inferredTypeArray.debugDummy()

// The Section protocol can only be used as a generic constraint since it has associatedType requirements, which means you can't mix different types that conforms to Section to the same array without changing the the type to Any
let all: [Section] = []

let mixedArray = [explicit, inferred] // Not allowed unless cast to [Any]
+3

Source: https://habr.com/ru/post/1016674/


All Articles