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 > <[email protected]> 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 > [email protected] > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list [email protected] https://lists.swift.org/mailman/listinfo/swift-evolution
