[swift-evolution] What about a VBA style with Statement?

Vladimir.S svabox at gmail.com
Mon Apr 18 10:03:22 CDT 2016


As for methods cascades, IMO it is a good feature and I support it as 
addition to 'with' feature. Method cascading can't be used to set/get 
values of multiply props, the main purpose of 'with'

I strongly feel that functions is not a solution for 'with' feature.
Functions add additional complexity, more possibilities for 
problems/errors, as we are creating the bock and calling it then.
It seems like functions allows to produce code that will compile, but will 
raise error on execution like
struct ST {
     var x = 5
}

with (ST) {  // just type here
     print($0.x)
}

and some number of similar problems. Also, why do we need parenthesis in 
with? Do we need them in "if"? in "for" ? in "switch"?

with s {
}

I believe "with" should be implemented as standard construction of the 
language. Opinions?

On 15.04.2016 5:12, Brent Royal-Gordon via swift-evolution wrote:
>>> I really think this settles the discussion, because methods cascades are *the* way to implement this kind of thing. (And for the record, I would prefer a SmallTalk/Dart-like syntax to a "with" statement.)
>>
>> It's been quite a while since the original discussion and I'm going to go all Brent R-G on the answer, which is I've come to prefer the Dart solution for cascading, think `with` is better suited for mutating copies of struct constants (Immutable setters, may not be language-inclusion suitable), and think binding self in closures is yet a third issue.
>>
>> Brent, concur?
>
> I'm not totally sold on Dart-style method cascading (although that's partly just the `..` syntax), but if that's been deferred to after Swift 3, then we're certainly in agreement on what we want now. :^)
>
> In terms of the `with` function, I think one version would handle both shorthanding a long variable name *and* modifying and returning a value:
>
> 	@discardableResult public func with<T>(_ value: T, user: @noescape inout T throws -> Void) rethrows -> T {
> 		var copy = value
> 		try user(&copy)
> 		return copy
> 	}
>
> At some point, they fixed the weird thing where you had to explicitly give the type of an inout closure parameter, so there's no syntactic penalty if you don't need to mutate. `user` could be `@noescape(once)` if that feature is ever added.
>
> In theory, it might be nice to have two versions, one mutating and one not, simply so you don't accidentally throw away a mutation:
>
> 	public func with<T>(_ value: T, user: @noescape inout T throws -> Void) rethrows -> T {
> 		var copy = value
> 		try user(&copy)
> 		return copy
> 	}
>
> 	public func with<T>(_ value: T, user: @noescape T throws -> Void) rethrows {
> 		try user(value)
> 	}
>
> In practice, however, Swift (or Swift 2 at least) seems to consider this ambiguous, so we're probably out of luck there.
>
> In terms of `self` parameters, I think the rule is simply this:
>
> * Functions and closures (but not methods) may give a parameter the internal name `self`.
> * If there is a `self` parameter, it behaves just as `self` in a method would—implicit method calls, special treatment in terms of capturing by closures, assignable only if it's `inout`, etc.
> * If a closure has a `self` parameter, there is no way to access the outer scope's `self`, just like any other shadowed variable.
>
> I would actually like to see `self` become as shadowable as any other variable, but there seems to be some resistance to that idea.
>
>
>
> P.S. Does that mean that blithely declaring that something is actually several orthogonal features is now a Royal decree?
>


More information about the swift-evolution mailing list