> On 8. Aug 2017, at 04:35, David Sweeris via swift-evolution
> <[email protected]> wrote:
>
>>
>> On Aug 7, 2017, at 3:00 PM, Logan Shire via swift-evolution
>> <[email protected] <mailto:[email protected]>> wrote:
>>
>> 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].
>
> What happens if you try to say "foos: [Foo<Any>] = ..."?
>
Foo<Int> and Foo<Any> are very different. Otherwise, you could take a Foo<Int>,
cast it to a Foo<Any> and set a String as its value.
I think what he means are partial generics, e.g: 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!
>
>
> The idiomatic solution would be to create a `Named` protocol with a `var
> name: String {get}` property, and write your function like `func sayHi(to
> foo:Named) {...}`. However, this `Named`protocol is really pretty trivial --
> its purpose is simply to "degenericify" a generic type, not to provide any
> semantic meaning. Perhaps an analogy could be drawn between such "trivial
> protocols" and how we sometimes view tuples as "trivial structs"? Dunno,
> maybe I'm just trying to turn two trees into a forest, but this kinda smells
> like it might be part of a bigger issue, and if it is I'd rather tackle that
> and then see if we still need to address anything here.
>
> +1, either way, though.
>
> - Dave Sweeris
> _______________________________________________
> swift-evolution mailing list
> [email protected] <mailto:[email protected]>
> https://lists.swift.org/mailman/listinfo/swift-evolution
> <https://lists.swift.org/mailman/listinfo/swift-evolution>
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution