[swift-evolution] [Pitch] Circling back to `with`
Greg Parker
gparker at apple.com
Tue May 31 04:14:13 CDT 2016
> On May 27, 2016, at 5:19 PM, Brent Royal-Gordon via swift-evolution <swift-evolution at swift.org> wrote:
>
>>> - A plain `with` whose closure parameter is not mutable and which is marked `@discardableResult`.
>>
>> I would like to see this version restricted to AnyObject. It has extremely limited utility with value types. It would usually be a mistake to call it with a value type.
>
> I would not. It gives you a way to give a value type a short, scoped, immutable alias:
>
> with(RareMagicalDeviceOwner.shared.spimsterWickets[randomIndex]) {
> print($0.turns)
> print($0.turnSpeed)
> }
>
> And in this form, there is no danger of mistakenly mutating the value type, because mutating methods would not be allowed:
>
> with(RareMagicalDeviceOwner.shared.spimsterWickets[randomIndex]) {
> $0.turnRepeatedly(times: 3) // Error: can't call mutating method on immutable parameter
> }
>
> To be clear, I'm not convinced there's a need to make any change from the proposed version at all. I'm spitballing alternate designs here, trying to see if there might be something a little better out there. But so far, I think the proposal balances the feature size against strictness pretty well, whereas these stricter designs I'm discussing increase the surface of the feature more than they improve it. This is a small (but significant!) convenience, and I feel pretty strongly that it should have a small implementation.
>
>> That said, I am not convinced these non-copying functions would be worth having after method cascades are introduced. Are there any use cases left for them in that future?
>
> Yes, absolutely. Method cascades have a narrow use case: methods on `self`. Not everything in Swift is a method, and not all methods are on `self`.
>
> with(tableView.cellForRow(at: indexPath).myLabel) { label in
> print("Constraining label: \(label)")
>
> NSLayoutConstraint.activate(
> NSLayoutConstraint.withVisualFormat("|-[label]-|", options: [], metrics: [:], views: ["label": label]) +
> NSLayoutConstraint.withVisualFormat("V:|[label]|", options: [], metrics: [:], views: ["label": label])
> )
>
> constrainedLabels.append(label)
> }
>
> None of the calls in that `with` block would benefit from method cascades, but they all benefit from `with`.
What are the differences or benefits of the above examples over the existing `do { let ... }` form?
do {
let w = RareMagicalDeviceOwner.shared.spimsterWickets[randomIndex]
print(w.turns)
print(w.turnSpeed)
}
do {
let label = tableView.cellForRow(at: indexPath).myLabel
print("Constraining label: \(label)")
NSLayoutConstraint.activate(
NSLayoutConstraint.withVisualFormat("|-[label]-|", options: [], metrics: [:], views: ["label": label]) +
NSLayoutConstraint.withVisualFormat("V:|[label]|", options: [], metrics: [:], views: ["label": label])
)
constrainedLabels.append(label)
}
--
Greg Parker gparker at apple.com Runtime Wrangler
More information about the swift-evolution
mailing list