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

Erica Sadun erica at ericasadun.com
Thu Feb 25 20:33:46 CST 2016


I'm really intrigued to see where this goes. Thanks, Stephen.

-- Erica

> On Feb 25, 2016, at 3:47 PM, Stephen Celis via swift-evolution <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
> - "Request for Discussion: Setup closures": 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
> - "Fluent syntax (replacing void with a useful default return value)": 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
> - "Scoped resources (like C# using statement)": http://thread.gmane.org/gmane.comp.lang.swift.evolution/1641
> - "Customized Inline Init Closure": http://thread.gmane.org/gmane.comp.lang.swift.evolution/1946
> - "Then Support": 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
> - "Custom default names for arguments of closures": http://thread.gmane.org/gmane.comp.lang.swift.evolution/6969
> - https://bugs.swift.org/browse/SR-160
> 
> [2] https://kotlinlang.org/docs/reference/lambdas.html#function-literals-with-receiver
> [3] https://github.com/devxoul/Then
> [4] https://github.com/Quick/Quick
> [5] https://github.com/kylef/Spectre
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution



More information about the swift-evolution mailing list