[swift-users] Capturing structs by reference
Zhao Xin
owenzx at gmail.com
Sun Jul 24 07:49:26 CDT 2016
Below code works.
struct MyValueType {
var x: () -> () {
return { print(self) }
}
init() {
// self.x = {
// print(self)
// }
}
}
let a = MyValueType()
a.x() // MyValueType()
Zhaoxin
On Sun, Jul 24, 2016 at 5:11 PM, Tyler Fleming Cloutier via swift-users <
swift-users at swift.org> wrote:
> Also if capture lists for structs do capture by value, how can I avoid the
> newly added error “Closure cannot implicitly capture a mutating self
> parameter” without changing the original reference semantics of MyValueType?
>
> Also why can’t I specify weak self for value types in capture lists if a
> captured value type is really just a reference anyway? What’s the purpose
> of that?
>
>
> On Jul 24, 2016, at 2:07 AM, Tyler Fleming Cloutier <cloutiertyler at aol.com>
> 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/b4bbeb87/attachment.html>
More information about the swift-users
mailing list