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

Reply via email to