[swift-evolution] [Pitch] [Phase 2] New `permuting` keyword for protocols

Adrian Zubarev adrian.zubarev at devandartist.com
Mon Dec 26 03:32:04 CST 2016


Hi Swift community,

I’d like you to think about the idea of being able to create protocols with a permutation path.

Recently I build a really tiny wrapper API around NSLayoutAnchor, where I wanted the user to have a nice and shiny API. The user can decide with which method he starts and optionally chain the other methods after that. The main restriction was that each method could only be used once, which is what a permutation offers. For that project I had to model and overload over 30 protocols, which overlaps only 5 different methods. If I had to add more methods, the permutation protocol model would silly explode.

You can look up a visual graph here: https://github.com/DevAndArtist/swift-functionallayout

My pitch is purely additive and could be considered during phase 2!

Similar to indirect the new keyword would be applied to protocol members or to the protocol itself.

protocol Foo {
      permuting mutating func foo() -> Foo
      permuting mutating func boo() -> Foo
      permuting mutating func zoo() -> Foo
       
      func bar() -> EscapingType
       
      var x: Foo { get } // returns a new permutation path
}

permuting protocol Boo {
      func a() -> Boo
      func b() -> Boo
       
      func c() -> EscapingType
       
      var x: Boo { get } // participates in the current permutation chain
}
Example with Foo:

class A : Foo {
    permuting mutating func foo() -> Foo { return self }
    permuting mutating func boo() -> Foo { return self }
       
    func bar() -> EscapingType { return … }
       
    var x: Foo { return self }
}

let a = A().foo()

a.
// From here only the following part of `Foo` would be visible
//
// func boo() -> Foo
// func zoo() -> Foo
// func bar() -> EscapingType
// var x: Foo { get }
//
// `foo` is not visible because it's already used in the current permutation chain
//  

let aa = a.zoo()

//
// Visible API from `aa`
//
// func boo() -> Foo
// func bar() -> EscapingType
// var x: Foo { get }
//

aa.x.

//
// Since `x` is not marked with `permuting` keyword, it returns a new permutation chain where the whole `Foo` interface is again visible
//

aa.x.bar() // this will escape the permutation chain completely, because we're not returning `Foo` interface here  
Only a chain of members that returning the same protocol (or even Self?) and are marked with the permuting keyword are considered as part of the same permutation.

Members that are not permuting will either escape the permutation chain or create a new one, like bar or x in the example above.

Personally I think that would be a really handy tool for neat API design. It also helps to restrict some functional design while ease the build complexity.

My small wrapper API could be reduced to 3 protocols.



-- 
Adrian Zubarev
Sent with Airmail
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20161226/35571e31/attachment.html>


More information about the swift-evolution mailing list