Given `foo: T` and methods a(), b(), c(), d(), each of which can only be called once, how can the return value of these methods be represented in the type system?<br><br>That is, if `foo.a()` can be passed as an argument to an arbitrary function of type `(T) -> U`, either the function cannot immediately invoke a(), in which case foo is not of type T, or it can immediately invoke a(), in which case your keyword does not work.<br><br><div class="gmail_quote"><div dir="ltr">On Mon, Dec 26, 2016 at 04:32 Adrian Zubarev via swift-evolution <<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class="gmail_msg"><div class="m_5546036318609419609bloop_markdown gmail_msg"><p class="gmail_msg">Hi Swift community,</p>
<p class="gmail_msg">I’d like you to think about the idea of being able to create protocols with a permutation path.</p>
<p class="gmail_msg">Recently I build a really tiny wrapper API around <code class="gmail_msg">NSLayoutAnchor</code>, 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.</p>
<p class="gmail_msg">You can look up a visual graph here: <a href="https://github.com/DevAndArtist/swift-functionallayout" class="gmail_msg" target="_blank">https://github.com/DevAndArtist/swift-functionallayout</a></p>
<p class="gmail_msg">My pitch is purely additive and could be considered during phase 2!</p>
<p class="gmail_msg">Similar to <code class="gmail_msg">indirect</code> the new keyword would be applied to protocol members or to the protocol itself.</p>
<pre class="gmail_msg"><code class="m_5546036318609419609swift gmail_msg">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
}
</code></pre>
<p class="gmail_msg">Example with <code class="gmail_msg">Foo</code>:</p>
<pre class="gmail_msg"><code class="m_5546036318609419609swift gmail_msg">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
</code></pre>
<p class="gmail_msg">Only a chain of members that returning the same protocol (or even <code class="gmail_msg">Self</code>?) and are marked with the <code class="gmail_msg">permuting</code> keyword are considered as part of the same permutation. </p>
<p class="gmail_msg">Members that are not <code class="gmail_msg">permuting</code> will either escape the permutation chain or create a new one, like <code class="gmail_msg">bar</code> or <code class="gmail_msg">x</code> in the example above.</p>
<hr class="gmail_msg">
<p class="gmail_msg">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. </p>
<p class="gmail_msg">My small wrapper API could be reduced to 3 protocols. </p>
<p class="gmail_msg"></p></div><div class="m_5546036318609419609bloop_original_html gmail_msg"><div id="m_5546036318609419609bloop_customfont" style="font-family:Helvetica,Arial;font-size:13px;color:rgba(0,0,0,1.0);margin:0px;line-height:auto" class="gmail_msg"><br class="gmail_msg"></div><br class="gmail_msg"><div id="m_5546036318609419609bloop_sign_1482742492944386048" class="m_5546036318609419609bloop_sign gmail_msg"><div style="font-family:helvetica,arial;font-size:13px" class="gmail_msg">-- <br class="gmail_msg">Adrian Zubarev<br class="gmail_msg">Sent with Airmail</div></div></div><div class="m_5546036318609419609bloop_markdown gmail_msg"><p class="gmail_msg"></p></div></div>_______________________________________________<br class="gmail_msg">
swift-evolution mailing list<br class="gmail_msg">
<a href="mailto:swift-evolution@swift.org" class="gmail_msg" target="_blank">swift-evolution@swift.org</a><br class="gmail_msg">
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" class="gmail_msg" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class="gmail_msg">
</blockquote></div>