[swift-users] Capturing structs by reference

Zhao Xin owenzx at gmail.com
Sun Jul 24 07:56:41 CDT 2016


For the capture part, it is by strong reference as document says:

“By default, a closure expression captures constants and variables from its
> surrounding scope with strong references to those values. You can use a
> capture list to explicitly control how values are captured in a closure.”
> from: Apple Inc. “The Swift Programming Language (Swift 3 beta)”。 iBooks.
> https://itun.es/us/k5SW7.l



Zhaoxin




On Sun, Jul 24, 2016 at 5:07 PM, Tyler Fleming Cloutier via swift-users <
swift-users at swift.org> wrote:

> The Swift Programming Language book states:
>
> "Reference counting only applies to instances of classes. Structures and
> enumerations are value types, not reference types, and are not stored and
> passed by reference.”
>
> However consider the following example.
>
> func makeIncrementer() -> (() -> Int, () -> Int) {
>     var runningTotal = 0
>
>
>     func incrementer() -> Int {
>         runningTotal += 1
>         return runningTotal
>     }
>
>
>     func incrementer2() -> Int {
>         runningTotal += 1
>         return runningTotal
>     }
>
>
>     return (incrementer, incrementer2)
> }
>
> let x = makeIncrementer()
>
> x.0() // 1
> x.1() // 2
>
> Clearly runningTotal is captured by reference by both incrementer and
> incrementer2. Is closure capturing the only case in which value types are
> treated as reference types?
>
> Why wouldn’t Swift be implement so that runningTotal was Captured as a
> static copy at the time of capture so that each of the incrementer
> functions has their own “value”?
>
> It seems like you could pretty easily run into a retain cycle with a
> struct even though it is a value type!
>
> Consider:
>
> struct MyValueType {
>
>
>     var x: () -> ()
>
>
>     init() {
>         self.x = {
>             print(self)
>         }
>     }
>
>
> }
>
> One might imagine that the capture of a value type like MyValueType would
> make a static copy of self for the closure, but if I understand correctly I
> actually just get a retain cycle. But it’s even worse, because (as I
> understand it) whether I do or not is optimization dependent!
>
> "As an optimization, Swift may instead capture and store a *copy* of a
> value if that value is not mutated by a closure, and if the value is not
> mutated after the closure is created.”
>
> Now it turns out that as of SE-0035 I get an error for the above code.
> Namely,
>
> “Closure cannot implicitly capture a mutating self parameter.”
>
> Kind of a strange error message for two reasons. The first is that nothing
> appears to be doing any mutating or declaring an intention of mutating. The
> second is that it’s not clear at all (to me at least) how to go about
> remedying the issue.
>
> If I capture self explicitly with something like [s = self], am I getting
> a copy of self or a reference to self? I would assume a copy of self, but
> that’s not super clear given the somewhat surprising behavior of capturing
> value types by reference.
>
> I would think the following would be a valid solution. Is there a better
> one?
>
> struct MyValueType {
>
>
>     var x: (() -> ())!
>
>
>     init() {
>         self.x = nil
>         self.x = { [s = self] in
>             print(s)
>         }
>     }
>
>
> }
>
> Is there a way to use currying to be more explicit about the semantics of
> passing a value into a closure?
>
> Any help or discussion would be much appreciated!
>
> Tyler
>
>
>
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20160724/6158540e/attachment.html>


More information about the swift-users mailing list