let dateFormatter = with(DateFormatter()) {
let `self` = $0
self.dateStyle = .short
self.timeStyle = .long
}
I'm not super happy about the $0 sticking around but it's a lot cleaner than it used to be. However, I believe @Chris_Lattner3 has called this an abomination so it's unlikely that this would be used as a motivating case. Ideally, there would be a way to scope to a variable without having to use either abomination or $0.
Doesn’t this follow from the shadowing option (#1) in that thread? In that thread I shared another example where this kind of self shadowing by a closure argument would be useful.
The automatic-ness of the Kotlin design makes me wrinkle my nose a bit. Having a little bit of notation in the closure literal to show that self rebinding is happening seems like a small price for writers to pay for the benefit of anyone reading the code. It also puts control of the feature completely in the author's hand; they don't only get to use it where the API author allowed them to. If we do end up allowing you to rebind self in guards and if-lets, then it also feels like one coherent feature, as @anandabits said.
I can see a manual rebinding case being useful, but while you may be right that the capture is useful to call out the rebinding, I think the use of with will do that too. Automatic binding allows users to drop the boilerplate from the common case, as we see in several Swift features.
If we want to enable binding self automatically, would that only work for with, or could we make a generally useful feature out of this?
Ruby has instance_exec, which executes a block in the context of some object. This method is what makes Ruby so great for building DSLs, and I could see a feature where a function can declare it will execute a closure with self bound to an instance of some type as a nice general-purpose addition to Swift. Maybe the syntax could be as simple as allowing something like an @self annotation once in the parameter type list of a closure type.
Yes. I'd rather have self-rebinding being activated on the method definition rather than at the call site. Self-rebinding at the call site is seducing because it is more general, but it would pollute all calls to with or similar convenience method whose purpose it to streamline boring code.
I kind of agree with this. I've seen some people struggle with Kotlin precisely because of all the magic that does and by having different keywords that do too similar things.
Also is important to think about how accessing the enclosing type would look like in terms of shadowing self. (i.e: how I access a property in the class from code inside the "with" if self is being shadowed)
Not a crazy idea. Going even further some languages have a "using Type/Instance" keyword that rebinds the names in that object to the current scope. Probably Swift doesn't want that but still, something powerful that we could keep in mind.
Yes, it might look odd, but I'd expect "<-" to be an assignment or to feed something to the item on the left, and "with" could mean anything.
On the other hand, interpreting "2 * (5, 10)" as "(2 * 5, 2 * 10)" feels very natural for me.
I lean towards feeling that the gain in clarity that comes with explicit rebinding is worth it. On the other hand I am sympathetic to the position that explicit rebinding could become boilerplate-y in some settings (specifically builder style DSLs). Imagine the following HTML builder (inspired by https://kotlinlang.org/docs/reference/type-safe-builders.html):
html { self in
head { self in
}
body { self in
}
}
If supporting these use cases is important perhaps there could be a shorthand for single-argument closures that bind the argument to self. Something like {@ ... } which reduces the 7 characters of self in to a single @. This would provide most of the syntactic benefit of implicit rebinding without losing clarity. (Note: this is strawman syntax, to demonstrate the concept, not a well thought out proposal)
The above example might be streamlined to the following:
html {@
head {@
}
body {@
}
}
This is pretty close to the original Kotlin without the potential for confusion. Readers who are unfamiliar with the DSL but familiar with Swift would immediately have a pretty good idea of what is going on.