[swift-evolution] [Discussion] Here we go again: Extension Functions

Pierre Monod-Broca pierre at monod-broca.fr
Tue Mar 1 05:14:37 CST 2016


+1 on changing the meaning of `self`, it's scary

> Le 29 févr. 2016 à 13:33, Radosław Pietruszewski via swift-evolution <swift-evolution at swift.org> a écrit :
> 
> I have chills when I hear the idea of a closure changing the `self` from underneath me. JavaScript made me this way.
> 
> Of course, this is different than JavaScript, because it’s type-safe and you have to explicitly make a specific closure behave this way.
> 
> Still:
> - I fear that this can be awfully confusing because there’s no indication on call site that the closure has a different `self`.
> - 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 :(
> 
> 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 (https://github.com/devxoul/Then#trouble-shooting <https://github.com/devxoul/Then#trouble-shooting>). But maybe it’s not the way to go.
> 
> — Radek
> 
>> On 25 Feb 2016, at 23:47, Stephen Celis via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> I'm reopening a topic that has already been discussed here at length[1]: setup closures and `self`-binding closures.
>> 
>> 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.
>> 
>> Erica's earlier draft proposed this builder pattern:
>> 
>>    with let task = NSTask() {
>>        launchPath = "/usr/bin/mdfind"
>>        arguments = ["kMDItemDisplayName == *.playground"]
>>        standardOutput = pipe
>>    }
>> 
>> With extension functions, we could approach something similar:
>> 
>>    func with<T>(value: T, body: T.() -> ()) -> T {
>>        value.body()
>>        return value
>>    }
>> 
>>    let task = with(NSTask()) {
>>        launchPath = "/usr/bin/mdfind"
>>        arguments = ["kMDItemDisplayName == *.playground"]
>>        standardOutput = pipe
>>    }
>> 
>> Or, using the `then`[3] pattern:
>> 
>>    protocol Builder {}
>>    extension Builder {
>>        func then(body: Self.() -> ()) -> Self {
>>            body()
>>            return self
>>        }
>>    }
>>    extension NSTask: Builder {}
>> 
>>    let task = NSTask().then {
>>        launchPath = "/usr/bin/mdfind"
>>        arguments = ["kMDItemDisplayName == *.playground"]
>>        standardOutput = pipe
>>    }
>> 
>> How about BDD-style frameworks (like Quick/Nimble[4] and Spectre[5])?
>> 
>>    describe("a person") {
>>        let person = Person(name: "Kyle")
>> 
>>        it("has a name") {
>>            try expect(person.name) == "Kyle"
>>        }
>>    }
>> 
>> And HTML builders?
>> 
>>    html {
>>        head { title("Hello, World!") }
>>    }
>> 
>> And block-based, transactional APIs?
>> 
>>    db.inTransaction {
>>        delete("users", "first_name = ?", ["Jake"])
>>    }
>> 
>> The main benefits have been previously discussed:
>> 
>> 1. The ability to remove noise ("$0" everywhere)
>> 2. The ability to avoid defining globals (in favor of a safer, scoped interface)
>> 
>> Would such an enhancement be feasible?
>> 
>> ---
>> Stephen
>> 
>> Footnotes:
>> 
>> [1] A probably-incomplete list:
>> - "Idea for enabling DSLs: bind to self in closures": https://lists.swift.org/pipermail/swift-evolution/2015-December/000114.html <https://lists.swift.org/pipermail/swift-evolution/2015-December/000114.html>
>> - "Request for Discussion: Setup closures": https://lists.swift.org/pipermail/swift-evolution/2015-December/000211.html <https://lists.swift.org/pipermail/swift-evolution/2015-December/000211.html>
>> - "Method cascading (was Re: Request for Discussion: Setup closures)": https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151130/000729.html <https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20151130/000729.html>
>> - "Fluent syntax (replacing void with a useful default return value)": http://thread.gmane.org/gmane.comp.lang.swift.evolution/374 <http://thread.gmane.org/gmane.comp.lang.swift.evolution/374>
>> - "Lexical scope statement (with .. do)": http://thread.gmane.org/gmane.comp.lang.swift.evolution/1408 <http://thread.gmane.org/gmane.comp.lang.swift.evolution/1408>
>> - "Scoped resources (like C# using statement)": http://thread.gmane.org/gmane.comp.lang.swift.evolution/1641 <http://thread.gmane.org/gmane.comp.lang.swift.evolution/1641>
>> - "Customized Inline Init Closure": http://thread.gmane.org/gmane.comp.lang.swift.evolution/1946 <http://thread.gmane.org/gmane.comp.lang.swift.evolution/1946>
>> - "Then Support": http://thread.gmane.org/gmane.comp.lang.swift.evolution/2054 <http://thread.gmane.org/gmane.comp.lang.swift.evolution/2054>
>> - "Draft proposal: multi-property assignment .= operator": http://thread.gmane.org/gmane.comp.lang.swift.evolution/2960 <http://thread.gmane.org/gmane.comp.lang.swift.evolution/2960>
>> - "Custom default names for arguments of closures": http://thread.gmane.org/gmane.comp.lang.swift.evolution/6969 <http://thread.gmane.org/gmane.comp.lang.swift.evolution/6969>
>> - https://bugs.swift.org/browse/SR-160 <https://bugs.swift.org/browse/SR-160>
>> 
>> [2] https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver <https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver>
>> [3] https://github.com/devxoul/Then <https://github.com/devxoul/Then>
>> [4] https://github.com/Quick/Quick <https://github.com/Quick/Quick>
>> [5] https://github.com/kylef/Spectre <https://github.com/kylef/Spectre>
>> 
>> _______________________________________________
>> swift-evolution mailing list
>> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-evolution
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160301/5881a786/attachment.html>


More information about the swift-evolution mailing list