[swift-evolution] [Proposal] Protocols on Steroids

Howard Lovatt howard.lovatt at gmail.com
Wed Dec 30 16:50:44 CST 2015


Proposal: Protocols on Steroids
=======================

Change the way protocols and generics work, in particular:
Generic protocol with type parameters inside `<>`, like classes and structs
Allow covariant return types including for generic types
Allow covariant generic argument types with a runtime check that it is of the correct type
Treat Self as a shorthand for the type name; in particular as though there was an extra genetic type, `Type<Self: Type>` and everywhere `Self` appeared in the body the compiler substitutes `Type`
Allow `GenericTypeName.dynamicType` to return the metatype of a generic type
Treat typealias as introducing a generic type parameter that is not part of the type's type signature (or whatever it is renamed to)
Allow implementations in protocols as well as in extensions to protocols (I think this is on the cards already)
Allow default stored properties and default inits in protocol, see `Holder` example below
Disallow overload of a function with a generically typed argument with a function whose argument is derived from the generic type, must be an override.
Implications
------------
Arrays and a like become covariant (with runtime type check for write) - like Java arrays but not Java Lists
`Equatable` and co would not be a special type, could have arrays of `Equatable`s
No need for `AnyXXX` types, the protocol does this directly
No need for `CollectionType` and `Array`, `Array` would become a `protocol` and a `struct`

Example
--------
A holder of 1 value (chosen to keep the example short - think of it as an array):

    protocol Holder<T> {
        default var value: T // See implementation below for what default does
    }

In use it could be used like:

    var holder = Holder(value: 1) // Holder<Int>
    func printout(value: Holder<Any>) {
        print("\(value.value)")
    }
    printout(holder) // Passing a Holder<Int> to a Holder<Any> OK

Implementation
----------------
The above example would be translated by the compiler to something like (though the names would be changed - names chosen to spell out what is happening):

    protocol Holder<T> { // Retains generic type because protocols are types
        var value: T { get set }
    }

    struct DefaultHolder<T>: Holder<T> { // Written because protocol had a default implementation
        var value: T
    }

    struct HolderInt: DefaultHolder<Int> { // Written because a `Holder<Int>` was created
        var _value: Int
        var value: Int {
            get {
                return _value
            }
            set {
                let temp = newValue as! Int // Runtime type check for write
                _value = temp
            }
    }


Other languages
-----------------
This is how Java arrays work, but not Java generics which are cumbersome to use in practice but do offer static type checking on write which neither this proposal or Java arrays offer. Java arrays use a runtime type check.
Dynamic languages and Obj-C normally allow you to store anything in an array (NSArray). This is different than the behaviour proposed, an array would be covariant, i.e. a `[Hashable]` could store anything derived from `Hashable` but could not store an `Equatable` or an `Any` that were not `Hashable`. But the array could be passed to a function expecting an `[Any]`, for example, and that function could read from the array.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151231/06ace647/attachment.html>


More information about the swift-evolution mailing list