[swift-evolution] [Proposal Draft] automatic protocol forwarding

Félix Cloutier felixcca at yahoo.ca
Tue Dec 29 14:26:26 CST 2015


As the resident you-can-already-do-this grumpy guy, I tend to agree that most protocols aren't easily amenable to forwarding, and this solution works too.

In general, I think that Swift already doesn't impose too much boilerplate, and I think that most features to reduce boilerplate would be better served by having a sane macro system in Swift. (This is probably not in scope for Swift 3, though.)

Félix

> Le 29 déc. 2015 à 15:06:48, Kevin Ballard via swift-evolution <swift-evolution at swift.org> a écrit :
> 
> I briefly skimmed your proposal, so I apologize if you already addressed this, but it occurs to me that we could support automatic protocol forwarding today on a per-protocol basis simply by declaring a separate protocol that provides default implementations doing the forwarding. Handling of Self return types can then be done by adding a required initializer (or just not implementing that method, so the concrete type is forced to deal with it even though everything else is forwarded).
>  
> For example, if I want to automatically forward SequenceType to a member, I can do something like
>  
> protocol SequenceTypeForwarder : SequenceType {
>     typealias ForwardedSequenceType : SequenceType
> 
>     var forwardedSequence : ForwardedSequenceType { get }
> }
> 
> extension SequenceTypeForwarder {
>     func generate() -> ForwardedSequenceType.Generator {
>         return forwardedSequence.generate()
>     }
> 
>     func underestimateCount() -> Int {
>         return forwardedSequence.underestimateCount()
>     }
> 
>     func map<T>(@noescape transform: (ForwardedSequenceType.Generator.Element) throws -> T) rethrows -> [T] {
>         return try forwardedSequence.map(transform)
>     }
> 
>     func filter(@noescape includeElement: (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> [ForwardedSequenceType.Generator.Element] {
>         return try forwardedSequence.filter(includeElement)
>     }
> 
>     func forEach(@noescape body: (ForwardedSequenceType.Generator.Element) throws -> Void) rethrows {
>         return try forwardedSequence.forEach(body)
>     }
> 
>     func dropFirst(n: Int) -> ForwardedSequenceType.SubSequence {
>         return forwardedSequence.dropFirst(n)
>     }
> 
>     func dropLast(n: Int) -> ForwardedSequenceType.SubSequence {
>         return forwardedSequence.dropLast(n)
>     }
> 
>     func prefix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
>         return forwardedSequence.prefix(maxLength)
>     }
> 
>     func suffix(maxLength: Int) -> ForwardedSequenceType.SubSequence {
>         return forwardedSequence.suffix(maxLength)
>     }
> 
>     func split(maxSplit: Int, allowEmptySlices: Bool, @noescape isSeparator: (ForwardedSequenceType.Generator.Element) throws -> Bool) rethrows -> [ForwardedSequenceType.SubSequence] {
>         return try forwardedSequence.split(maxSplit, allowEmptySlices: allowEmptySlices, isSeparator: isSeparator)
>     }
> }
>  
> With this protocol declared, I can then say something like
>  
> struct Foo {
>     var ary: [Int]
> }
> 
> extension Foo : SequenceTypeForwarder {
>     var forwardedSequence: [Int] { return ary }
> }
>  
> and my struct Foo now automatically implements SequenceType by forwarding to its variable `ary`.
>  
> The downside to this is it needs to be manually declared for each protocol. But I wager that most protocols actually aren't really amenable to forwarding anyway.
>  
> -Kevin Ballard
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

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


More information about the swift-evolution mailing list