[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