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

Pierre Monod-Broca pierre at monod-broca.fr
Fri Feb 26 06:21:47 CST 2016


+1 on the idea.

I'm less convinced by the suggested syntax, to me it feels a bit weird.

I'm thinking an attribute on the closure's first parameter, for exemple (feel free to suggest other names):

func with<T>(value: T, body: (bound T) -> ()) -> T {
    body(value)
    return value
}


> Le 26 févr. 2016 à 08:22, Eugene Gubin via swift-evolution <swift-evolution at swift.org> a écrit :
> 
> +1 very interesting idea
> 
> 2016-02-26 9:09 GMT+03:00 Russ Bishop via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>>:
> +1 to this or something like it.
> 
> Right now I’m relying on crap^H^H^H^Hstuff like dispatch_get_specific to provide that kind of context without introducing something like Quick’s global “World”.
> 
> Russ
> 
> > On Feb 25, 2016, at 2:47 PM, 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 <http://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 <https://lists.swift.org/mailman/listinfo/swift-evolution>
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org <mailto:swift-evolution at swift.org>
> https://lists.swift.org/mailman/listinfo/swift-evolution <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/20160226/7ea8ea0a/attachment.html>


More information about the swift-evolution mailing list