<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=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 3, 2015, at 10:28 PM, David Waite <<a href="mailto:david@alkaline-solutions.com" class="">david@alkaline-solutions.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">( Originally proposed here: <a href="https://forums.developer.apple.com/thread/13806" class="">https://forums.developer.apple.com/thread/13806</a> )<div class=""><br class=""></div><div class="">Often, frameworks will wish to provide a domain specific language for configuring or composition. Web frameworks for instance may define methods like</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">get(“/“) { request, result in … }</font></div><div class=""><br class=""></div><div class="">Testing frameworks (such as Quick/Nimble) may wish to define a terse and expressive syntax for defining behavioral tests:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">describe("the 'Documentation' directory") {</font><div class=""><font face="Menlo" class=""> it("has everything you need to get started") {</font></div><font face="Menlo" class=""> let sections = Directory("Documentation").sections</font></div><div class=""><div class=""><font face="Menlo" class=""> expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups”))</font></div></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><div class=""><br class=""></div></div><div class="">While expressive, this has a big problem - describe, it, expect and contain are now defined as either global functions (which cause namespace pollution and mandate global state) or instance methods on a class (which requires the use of class inheritance, and is limited by single class inheritance)</div><div class=""><br class=""></div><div class="">You could have some sort of context object passed into the closure instead:</div><div class=""><br class=""></div><div class=""><font face="Menlo" class="">protocol SpecBuilder {</font></div><div class=""><font face="Menlo" class=""> func describe(description:String, inner:(QuickSpecContext)->())</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">protocol QuickSpecContext {</font></div><div class=""><font face="Menlo" class=""> func it(description:String, inner:(QuickSpecContext)->()) </font></div><div class=""><font face="Menlo" class=""> func expect<T>(statement:@autoclosure ()->T, file: StaticString = __FILE__, line: UWord = __LINE__ ) -> Expectation<T></font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><font face="Menlo" class=""><br class=""></font></div><div class=""><font face="Menlo" class="">var spec = QuickSpecBuilder(config)</font></div><div class=""><font face="Menlo" class="">spec.describe("the 'Documentation' directory") {</font></div><div class=""><font face="Menlo" class=""> context in</font></div><div class=""><div class=""><font face="Menlo" class=""> <a href="http://context.it/" class="">context.it</a>("has everything you need to get started") {</font></div><font face="Menlo" class=""> context in</font></div><div class=""><font face="Menlo" class=""> let sections = Directory("Documentation").sections</font></div><div class=""><font face="Menlo" class=""> context.expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups”))</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div><div class=""><br class=""></div><div class="">But this has significantly more noise. So my proposal is to allow for a closure argument to be used as the current type instance- to be able to redefine ‘self’ within a block.</div><div class=""><br class=""></div><div class=""><div class=""><font face="Menlo" class="">var spec = QuickSpecBuilder(config)</font></div><div class=""><font face="Menlo" class="">spec.describe("the 'Documentation' directory") {</font></div><div class=""><font face="Menlo" class=""> self in</font></div><div class=""><div class=""><font face="Menlo" class=""> it("has everything you need to get started") {</font></div><font face="Menlo" class=""> self in</font></div><div class=""><font face="Menlo" class=""> let sections = Directory("Documentation").sections</font></div><div class=""><font face="Menlo" class=""> expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups”))</font></div><div class=""><font face="Menlo" class=""> }</font></div><div class=""><font face="Menlo" class="">}</font></div></div><div class=""><br class=""></div><div class="">resolution remains the same (lexical scope shadowing the type), this is merely shorthand to allow expressive grammars without requiring class inheritance or global functions. It also remains optional to use - the last two examples are based around the same protocols and should compile to the same code.</div><div class=""><br class=""></div><div class="">I considered alternate syntaxes to express this, mostly alternatives on the bracketing of the closure itself to indicate binding a parameter to self. In the end, I decided:</div><div class="">1. When a block has multiple parameters, you would still need syntax decide which, if any, is bound to self</div><div class="">2. The language complexity in having another syntax for expressing closures with different behavior may not be worth it</div><div class="">3. Code would be confusing for those not knowing the new syntax. “self in” is (comparatively) straightforward and descriptive</div></div></div></blockquote><br class=""></div><div>Another way to do this would be to support scoped imports, to make a set of top-level functions locally available without polluting the global namespace:</div><div><br class=""></div><div>{</div><div> import func QuickSpecBuilder.expect</div><div><br class=""></div><div> expect(sections).to(....)</div><div>}</div><br class=""><div class="">Being able to elide self is already somewhat controversial, and a number of people find it makes code harder to read. I worry that allowing closures to change 'self' has the potential to be even more confusing. In Javascript, it's my understanding the ability to arbitrarily rebind 'this' is seen as a design flaw rather than a feature people regularly take advantage of.</div><div class=""><br class=""></div><div class="">-Joe</div></body></html>