[swift-evolution] [Pitch] Improving unspecified generic usability

Logan Shire logan.shire at gmail.com
Mon Aug 7 17:00:33 CDT 2017


One of my longstanding frustrations with generic types and protocols has been how hard it is to work with them when their type is unspecified.
Often I find myself wishing that I could write a function that takes a generic type or protocol as a parameter, but doesn’t care what its generic type is.

For example, if I have a type:

struct Foo<T> {
    let name: String
    let value: T
}

or:

protocol Foo {
    associatedtype T
    var name: String { get }
    var value: T { get }
}

And I want to write a function that only cares about Foo.name, I’d like to be able to:

func sayHi(to foo: Foo) {
    print("hi \(foo.name)")
}

But instead I get the error, “Reference to generic type Foo requires arguments in <…>”

Also, when you want to have a polymorphic array of generic types, you can’t:

let foos: [Foo] = [Foo(name: "Int", value: 2), Foo(name: "Double", value: 2.0)]

And if you remove the explicit type coercion, you just get [Any]

let foos = [Foo(name: "Int", value: 2), Foo(name: "Double", value: 2.0)]

I wish that could be inferred to be [Foo]. I’d like to propose being able to use the non-generic interface of a type normally. 
I.e. if you have a type Foo<T>, it is implicitly of type Foo as well. The type Foo could be used like any other type.
It could be a parameter in a function, a variable, or even the generic type of another type (like a Dictionary<String, Foo>)

The only restriction is that if you want to call or access, directly or indirectly, a function or member that requires the generic type,
the generic type would have to be known at that point.

Foo<T> should be able to be implicitly casted to Foo wherever you want, and Foo could be cast to Foo<T> conditionally.
Initializers would still obviously have to know the generic type, but given the above example, you should be able to:

let names = foos.map { $0.name }

However, you could not do the following:

let foos = [Foo]()

Because the initializer would need to know the generic type in order to allocate the memory.

Let me know what you think!

—

Logan Shire
iOS @ Lyft

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


More information about the swift-evolution mailing list