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

Kevin Ballard kevin at sb.org
Tue Dec 29 14:06:48 CST 2015

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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20151229/55040fdf/attachment.html>

More information about the swift-evolution mailing list