>> 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?

-- 
Brent Royal-Gordon
Architechies

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to