[swift-evolution] Binding generic types using a metatype parameter

Joe Groff jgroff at apple.com
Thu Mar 24 12:19:24 CDT 2016


> On Mar 23, 2016, at 11:29 AM, Joanna Carter <joanna at carterconsulting.org.uk> wrote:
> 
> Hi Joe
> 
>> 
>> You can accomplish this with Swift today by casting your Any.Type to a Protocol.Type that provides an initializer:
>> 
>> protocol Deserializable {
>> init(deserializedFrom stream: DeserializationStream)
>> }
>> 
>> func deserializeValue(type type: Any.Type, from stream: DeserializationStream) -> Any? {
>> if let deserializableType = type as? Deserializable.Type {
>>   return deserializableType.init(deserializedFrom: stream)
>> }
>> return nil
>> }
> 
> Hmm… I've been playing with this for days now and, as useful as your code is for instantiating a given type, what I need to do is instantiate a generic type, bound to that given type.
> 
> Something along the lines of…
> 
> public protocol PropertyProtocol
> {
>  var untypedValue: Any? { get }
> }
> 
> public struct Property<PropertyType : Any>
> {
>  public let info: PropertyInfo
> 
>  public var name: String
>  {
>    return info.name
>  }
> 
>  public var displayName: String
>  {
>    return info.displayName
>  }
> 
>  public var value: PropertyType?
> 
>  public init()
>  {
>    self.init(propertyInfo: PropertyInfo(), value: nil)
>  }
> 
>  init(propertyInfo: PropertyInfo, value: PropertyType?)
>  {
>    self.value = value
> 
>    self.info = propertyInfo;
>  }
> 
>  init(propertyInfo: PropertyInfo)
>  {
>    self.init(propertyInfo: propertyInfo, value: nil)
>  }
> 
>  init(other: Property<PropertyType>)
>  {
>    self.init(propertyInfo: other.info, value: other.value)
>  }
> }
> 
> struct PropertyFactory
> {
>  static func createBoundPropertywithValueType(valueType: Any.Type) -> PropertyProtocol
>  {
>    return Property<valueType>.init()
>  }
> }
> 
> Of course, Ive still got a lot of C# cruft in my thinking so I am more than willing to admit I may not be approaching this in the right way ;-)

Sorry for not getting back to you sooner. What's necessary here is a way to "open" the type of Any.Type, turning it back into something the compiler considers as a type instead of a value. This is something we've discussed having better support for, but right now there's only a sneaky way to do it using protocol extensions. If you constrain Property's type parameter to a protocol:

protocol PropertyType {}
struct Property<T: PropertyType>: PropertyProtocol {}

then you can add a static method to PropertyType in an extension, which can use Self as the opened dynamic type:

extension PropertyType {
  private static func create() -> Property<Self> {
    return Property<Self>.init()
  }
}

and delegate to that extension method in your factory function:

struct PropertyFactory {
  static func createBoundPropertywithValueType(valueType: PropertyType.Type) -> PropertyProtocol
  {
    return valueType.create()
  }
}

-Joe

> struct PropertyFactory
> {
>  static func createBoundPropertywithValueType(valueType: Any.Type) -> PropertyProtocol
>  {
>    return Property<valueType>.init()
>  }
> }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160324/1753382a/attachment.html>


More information about the swift-evolution mailing list