[swift-evolution] Generic parameters in "as?" checks

Charles Srstka cocoadev at charlessoft.com
Wed Jan 20 23:53:31 CST 2016


> On Jan 20, 2016, at 11:26 PM, Slava Pestov <spestov at apple.com> wrote:
> 
> Here’s an attempt to implement this with existing language features:
> 
>> protocol HasElementType {
>>   func getElement() -> Any.Type?
>> }
>> 
>> extension HasElementType {
>>   func getElement() -> Any.Type? {
>>     return nil
>>   }
>> }
>> 
>> extension Array : HasElementType {
>>   func getElement() -> Any.Type? {
>>     return Element.self
>>   }
>> }
>> 
>> func isArrayWithElementType<T>(a: Any, _ m: T.Type) -> Bool {
>>   guard let aa = a as? HasElementType else { return false }
>>   guard let elt = aa.getElement() else { return false }
>>   return elt is T.Type
>> }
>> 
>> protocol P {}
>> struct X : P {}
>> 
>> print(isArrayWithElementType([1,2,3,4,5], Int.self))
>> print(isArrayWithElementType([1,2,3,4,5], Float.self))
>> print(isArrayWithElementType(["a", "b"], String.self))
>> print(isArrayWithElementType([X()], X.self))
>> print(isArrayWithElementType([X()], P.self))

Thanks for that. The trouble is that the problem I’m trying to solve is actually more complicated than the example; it’s not actually Array that I’m dealing with, but a custom type. I am looking for a way not just to see whether the thing contains a certain type, but actually to cast it to the generic type with ‘as?’ so that I can use it as the generic type, pass it to functions that want that generic type, etc., do things with its type T that require something somewhere knowing what the type is (in my example, I used arr.append(T()), an operation that needs to know what type T is, so that it can create the instance. Just creating a Foo() wouldn’t work, since the array could be of some Foo subclass and not take garden-variety Foos.

If we want to get *really* specific, I’m actually dealing with a protocol with associated types, not a generic struct. However, they both fall under the same umbrella of “need to use this as a generic constraint”, and “generic” is less obnoxious to type over and over when discussing things than “protocol with associated types”. :-P

>> if let arr = someObject as? <T: Foo> Array<T> {
> 
> Yeah, it’s going to have to be this, since <T : Foo> is shorthand for <T where T : Foo>, and in general the <> of a bound generic type reference are different from <> in a generic signature — the latter introduces new type variables for instance.

Okay, in the example above, that leaves five places for the generic signature to go: after the “if”, after the “let”, after the variable name, after the equals sign, and after the “as?”. Or perhaps we could introduce some sort of new keyword in there to which to attach the generic signature.

>> Is this a feasible thing to ask for?
> 
> I think so, but we have to careful with the design. This ties in with some of the discussions on generalizing existential types, also.


That’s good to hear. Is there any information on what the Swift team is planning to do with existentials?

Charles

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160120/7442b0cf/attachment.html>


More information about the swift-evolution mailing list