Oscar Apeland
Oscar Apeland

Reputation: 6662

Switch on type contained in Array

I'd like to extract the type from an array passed as a parameter to a function, as to have the type parameter optional.

init(type: ContentType? = nil, style: LayoutStyle, content: [ContentProtocol]) {
    self.type = type ?? {
        switch content {
        case is [Ad]: return .ads
        case is [User]: return .users
        case is [List]: return .list
        default: fatalError("Can't assume.")
        }
    }()
}

Ad, User and List all conform to ContentProtocol.

These switch statements cause an error, "Optional type '[Ad/User/List]' cannot be used as a boolean; test for '!= nil' instead" which is not what I want to do.

This init however, does work.

init(type: ContentType? = nil, style: LayoutStyle, fetcher: ContentFetcher) {
    self.type = type ?? {
        switch fetcher {
        case is AdFetcher: return .ads
        case is UserFetcher: return .users
        case is ListFetcher: return .list
        default: fatalError("Can't assume.")
        }
    }()
}

ContentFetcher is another protocol, and all the types in the switch statement conforms to this.

Can I achieve the same as the last init with the first init?

Upvotes: 0

Views: 105

Answers (1)

user3441734
user3441734

Reputation: 17534

protocol P{}
struct A: P{}
struct B: P{}
struct C: P{}

let a = [A(), A()]
let b = [B(), B()]
let c = [C(), C()]

func foo(arr: [P]) {
    if let a = arr as? [A] {
        print(1, "A", a, type(of: a))
    } else if let b = arr as? [B] {
        print(1, "B", b, type(of: b))
    } else {
        print("not A nor B")
    }

    switch arr {
    case let a where a is [A]:
        print(2, "A", a, type(of: a))
    case let b where b is [B]:
        print(2, "B", b, type(of: b))
    default:
        print("not A nor B")
    }
    print()
}

foo(arr: a)
foo(arr: b)
foo(arr: c)

prints

1 A [__lldb_expr_245.A(), __lldb_expr_245.A()] Array<A>
2 A [__lldb_expr_245.A(), __lldb_expr_245.A()] Array<P>

1 B [__lldb_expr_245.B(), __lldb_expr_245.B()] Array<B>
2 B [__lldb_expr_245.B(), __lldb_expr_245.B()] Array<P>

not A nor B
not A nor B

if the input array is

let d:[P] = [A(), B()]

it prints

not A nor B
not A nor B

as expected

Upvotes: 0

Related Questions