<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class="">I have chills when I hear the idea of a closure changing the `self` from underneath me. JavaScript made me this way.</div><div class=""><br class=""></div><div class="">Of course, this is different than JavaScript, because it’s type-safe and you have to explicitly make a specific closure behave this way.</div><div class=""><br class=""></div><div class="">Still:</div><div class="">- I fear that this can be awfully confusing because there’s no indication on call site that the closure has a different `self`.</div><div class="">- what if you do want to use your “outer self” inside the self-binding closure? Sure, in some cases, you could differentiate by `foo` and `self.foo`, but I suspect most self-binding closures would also be @noescape. And so, back to the JavaScript-like convention of `let this = self`? Ugh :(</div><div class=""><br class=""></div><div class="">I do like that this syntax is not super noisy with all the $0’s, and also has the advantage that it doesn’t break when you only have a single expression (<a href="https://github.com/devxoul/Then#trouble-shooting" class="">https://github.com/devxoul/Then#trouble-shooting</a>). But maybe it’s not the way to go.</div><br class=""><div class="">
<div class="">— Radek</div>
</div>
<br class=""><div><blockquote type="cite" class=""><div class="">On 25 Feb 2016, at 23:47, Stephen Celis via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">I'm reopening a topic that has already been discussed here at length[1]: setup closures and `self`-binding closures.<br class=""><br class="">I've been wondering if Swift could adopt what Kotlin calls "extension function expressions"[2]. These would allow us to encode a closure's receiver type (`self`) into the closure type itself, providing a powerful, type-safe way to define DSLs.<br class=""><br class="">Erica's earlier draft proposed this builder pattern:<br class=""><br class=""> &nbsp;&nbsp;&nbsp;with let task = NSTask() {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;launchPath = "/usr/bin/mdfind"<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arguments = ["kMDItemDisplayName == *.playground"]<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;standardOutput = pipe<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class="">With extension functions, we could approach something similar:<br class=""><br class=""> &nbsp;&nbsp;&nbsp;func with&lt;T&gt;(value: T, body: T.() -&gt; ()) -&gt; T {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value.body()<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return value<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class=""> &nbsp;&nbsp;&nbsp;let task = with(NSTask()) {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;launchPath = "/usr/bin/mdfind"<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arguments = ["kMDItemDisplayName == *.playground"]<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;standardOutput = pipe<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class="">Or, using the `then`[3] pattern:<br class=""><br class=""> &nbsp;&nbsp;&nbsp;protocol Builder {}<br class=""> &nbsp;&nbsp;&nbsp;extension Builder {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func then(body: Self.() -&gt; ()) -&gt; Self {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;body()<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return self<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""> &nbsp;&nbsp;&nbsp;extension NSTask: Builder {}<br class=""><br class=""> &nbsp;&nbsp;&nbsp;let task = NSTask().then {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;launchPath = "/usr/bin/mdfind"<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;arguments = ["kMDItemDisplayName == *.playground"]<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;standardOutput = pipe<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class="">How about BDD-style frameworks (like Quick/Nimble[4] and Spectre[5])?<br class=""><br class=""> &nbsp;&nbsp;&nbsp;describe("a person") {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;let person = Person(name: "Kyle")<br class=""><br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;it("has a name") {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try expect(person.name) == "Kyle"<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class="">And HTML builders?<br class=""><br class=""> &nbsp;&nbsp;&nbsp;html {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;head { title("Hello, World!") }<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class="">And block-based, transactional APIs?<br class=""><br class=""> &nbsp;&nbsp;&nbsp;db.inTransaction {<br class=""> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete("users", "first_name = ?", ["Jake"])<br class=""> &nbsp;&nbsp;&nbsp;}<br class=""><br class="">The main benefits have been previously discussed:<br class=""><br class="">1. The ability to remove noise ("$0" everywhere)<br class="">2. The ability to avoid defining globals (in favor of a safer, scoped interface)<br class=""><br class="">Would such an enhancement be feasible?<br class=""><br class="">---<br class="">Stephen<br class=""><br class="">Footnotes:<br class=""><br class="">[1] A probably-incomplete list:<br class="">- "Idea for enabling DSLs: bind to self in closures": <a href="https://lists.swift.org/pipermail/swift-evolution/2015-December/000114.html" class="">https://lists.swift.org/pipermail/swift-evolution/2015-December/000114.html</a><br class="">- "Request for Discussion: Setup closures": <a href="https://lists.swift.org/pipermail/swift-evolution/2015-December/000211.html" class="">https://lists.swift.org/pipermail/swift-evolution/2015-December/000211.html</a><br class="">- "Method cascading (was Re: Request for Discussion: Setup closures)": <a href="https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151130/000729.html" class="">https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151130/000729.html</a><br class="">- "Fluent syntax (replacing void with a useful default return value)": <a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/374" class="">http://thread.gmane.org/gmane.comp.lang.swift.evolution/374</a><br class="">- "Lexical scope statement (with .. do)": <a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/1408" class="">http://thread.gmane.org/gmane.comp.lang.swift.evolution/1408</a><br class="">- "Scoped resources (like C# using statement)": <a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/1641" class="">http://thread.gmane.org/gmane.comp.lang.swift.evolution/1641</a><br class="">- "Customized Inline Init Closure": <a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/1946" class="">http://thread.gmane.org/gmane.comp.lang.swift.evolution/1946</a><br class="">- "Then Support": <a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/2054" class="">http://thread.gmane.org/gmane.comp.lang.swift.evolution/2054</a><br class="">- "Draft proposal: multi-property assignment .= operator": <a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/2960" class="">http://thread.gmane.org/gmane.comp.lang.swift.evolution/2960</a><br class="">- "Custom default names for arguments of closures": <a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/6969" class="">http://thread.gmane.org/gmane.comp.lang.swift.evolution/6969</a><br class="">- <a href="https://bugs.swift.org/browse/SR-160" class="">https://bugs.swift.org/browse/SR-160</a><br class=""><br class="">[2] <a href="https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver" class="">https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver</a><br class="">[3] <a href="https://github.com/devxoul/Then" class="">https://github.com/devxoul/Then</a><br class="">[4] <a href="https://github.com/Quick/Quick" class="">https://github.com/Quick/Quick</a><br class="">[5] <a href="https://github.com/kylef/Spectre" class="">https://github.com/kylef/Spectre</a><br class=""><br class="">_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></div></blockquote></div><br class=""></body></html>