[swift-evolution] Idea for enabling DSLs: bind to self in closures
David Waite
david at alkaline-solutions.com
Fri Dec 4 17:32:41 CST 2015
> On Dec 4, 2015, at 3:51 PM, Kevin Ballard <kevin at sb.org> wrote:
>
> On Fri, Dec 4, 2015, at 09:36 AM, Joe Groff wrote:
>> 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:
>>
>> {
>> import func QuickSpecBuilder.expect
>>
>> expect(sections).to(....)
>> }
>>
>> 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.
>
> I like this idea. I'm very much against rebinding `self` because it seems like an excellent source for confusion. Not only that, but the actual underlying desire here isn't to remove `self` at all, but just to introduce new functions into function resolution within a scope. And this is precisely what adding imports in arbitrary scopes does (the only downside being you need a line of code to add them, but that's not a big deal). I know Rust allows this and it's pretty handy. I'd love to have this feature even when not using a DSL.
>
> -Kevin Ballard
A few thoughts:
1. In a lot of situations they are not pure functions - they have state associated across them determined by the context in which your closure was called. So the import would not be of a static function, but of an input parameter, aka:
it(“…”) {
builder in
import builder
expect(sections).to{…}
}
Assuming expect is the only function, this may very well be equivalent to
it(“…”) {
builder in
let expect = builder.expect
expect(sections).to{…}
}
2. expect, in the case of Nimble, is an overloaded function. I assume import would bring in all overloads?
3. I like the idea of providing additional scope rather than overriding self, as you would likely need to bind self to a new name per my proposal (aka [my = self] self in…)
4. I like the idea of this having lexical scope, and import being usable outside of closures
5. Imports likely should generate conflicts at compile-time if they shadow defined functions if you can do wildcard imports. No need to have syntax to alias names - one should either change the code to not conflict or use the longer-form names
6. import could be an attribute:
it(“…”) {
@import builder in
expect(sections).to{…}
}
-DW
More information about the swift-evolution
mailing list