<p>Reference counting works best if there are no cycles. But closures that allow access to every variable in the parent scope by default automatically create cycles.</p>
<p>There are obvious solutions like only importing actually used or previously defined variables. There are also more advanced solutions like considering it like a member method and extend the lifetime of the parent only in that way i.e. using the same reference counter as the parent scope.</p>
<p>But I want to know the possibilities and varieties, and see whether there are more innovative ways.</p>

<garbage-collection><closure>
How do languages with only reference counting deal with closures?
CC BY-SA 4.0
2024-04-02T00:04:28.163Z
I think generally, regardless of the problem of reference cycles, any implementation of closures which cares about avoiding memory leaks will not retain local variables that aren't closed over; even if those references are cyclic, they are inaccessible, and retaining them would cause some garbage to be uncollectible. So what you describe as *"only import[ing] actually used ... variables"* is something we should assume about every implementation, unless garbage collection isn't a concern at all (in which case there is no question to answer).
kaya3
CC BY-SA 4.0
2024-04-02T00:07:55.323Z
Besides that, you could equally ask how languages with only reference counting deal with reference cycles in other objects that aren't closures. There are some interesting answers which aren't specific to the issue of closures, but which presumably also address the problem of recursive closures.
kaya3
CC BY-SA 4.0
2024-04-02T00:20:51.410Z
"Even if those references are cyclic, they are inaccessible". A reasonable point. Why didn't I think of that... But there is [a question asking for closures with mutual recursion](https://langdev.stackexchange.com/q/1682/1149). Combined with that it will still generate reference cycles. About answers not specific to closures, I don't know how to change the question to cover them, or whether I should without seeing how similar they are.
user23013
CC BY-SA 4.0
2024-04-02T00:30:12.190Z
Off the top of my head, the most common approach is to periodically check for cycles (not sure if this counts as "only reference counting"), or some languages just let reference cycles be memory leaks. [Lobster](https://aardappel.github.io/lobster/memory_management.html) is interesting, because it doesn't collect cycles, but programs run in debug mode issue a "cycle report" upon termination, giving information the programmer can use to break those cycles in their data structures (so that reference counting will be enough). Not specific to closures, but I think most approaches won't be.
kaya3
CC BY-SA 4.0
2024-04-02T00:32:24.140Z
One day a student came to Moon and said: "I understand how to make
a better garbage collector.  We must keep a reference count of the
pointers to each cons."

Moon patiently told the student the following story:

     "One day a student came to Moon and said: `I understand how to
     make a better garbage collector...
Michael Homer
CC BY-SA 4.0
2024-04-02T00:36:15.957Z
I think if you are limited to *only* reference counting, cyclic structures are inherently uncollectable, and closures aren't specifically different in that way in either making or being part of cycles. Is there something specific you're thinking of that motivates this framing (e.g. you have in mind a particular existing language designed with RC+special closure treatment, but aren't naming it)?
Michael Homer
CC BY-SA 4.0
2024-04-02T00:45:52.990Z
@kaya3 I'm more interested in the directions like weak references, that could be useful to many practical cases, though not solving everything. I'm more interested in allowing immediate destructors, than efficiency, memory leaks, etc, for which another backup garbage collector seem better.
user23013
CC BY-SA 4.0
2024-04-02T00:52:58.003Z
@MichaelHomer Actually I have listed a solution in the question, to use the same reference counter as the parent scope. (On this direction it ultimately would be static analysis of strongly connected components, which does work perfectly for a subdomain of the problem.) I haven't write code for garbage collection. See also the previous comment.
user23013
CC BY-SA 4.0
2024-04-02T01:21:39.510Z
" But closures that allow access to every variable in the parent scope by default automatically creates cycles."  Why?  Only if you can inject a reference to the closure into the parent scope.  But if you don't allow mutable bindings, there's no reason (and no way) to do that.  You can only get recusive bindings with an explicit `letrec` construct, and then you ensure all the mutaully recusive objects share a single reference count, and the internal refs between them are not reference counted.
Chris Dodd
CC BY-SA 4.0
2024-04-02T01:45:58.717Z
@ChrisDodd "Every variable in the parent scope" includes the one which refers to the closure, at least if it's a named closure. Anonymous closures wouldn't have that issue. But there are lots of languages which allow mutable bindings and don't require `letrec`.
kaya3
CC BY-SA 4.0
2024-04-02T02:28:40.377Z
Swift uses weak references, and closures can declare a capture list. See https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting#Strong-Reference-Cycles-for-Closures
Eldritch Conundrum
CC BY-SA 4.0
2024-04-02T03:40:02.913Z
@kaya3: Mutable bindings can lead to cycles that refcounting has problems with -- there's nothing special or different about closures.  Absent  mutable bindings, the newly created closure is bound in a new scope, not in the parent scope, so there's no cycles.  So if you don't allow mutable bindings and dont allow recursive binding (no letrec equivalent), then there are no cycles and closures are no different from any other object.  Even with letrec, you can handle that specially (basically, a single refcount for all the recusively bound things) and avoid cycles that way.
Chris Dodd
CC BY-SA 4.0
2024-04-02T03:43:33.010Z
@ChrisDodd In JavaScript, `const fib = x => n >= 2 ? fib(n-1) + fib(n-2) : n;` is a closure which closes over the local variable `fib`, which holds a reference to the closure. This is created without any mutable bindings and without a `letrec` keyword. This contradicts your statement that *"if you don't allow mutable bindings, [...] You can only get recusive bindings with an explicit `letrec` construct"*. Nonetheless, an answer which excludes the possibility of mutable bindings or recursion without `letrec` is not a very general answer, since that excludes so many languages.
kaya3
CC BY-SA 4.0
2024-04-02T03:45:45.120Z
@kaya3: That's an example of a letrec (even though it does not use that keyword), as the definition of fib used in the binding is recursive, not the definition from the containing scope.  Javascript, like many langauges, makes all bindings implicitly letrec.
Chris Dodd
CC BY-SA 4.0
2024-04-02T03:47:55.967Z
@ChrisDodd You said *"explicit `letrec` construct"*, which JavaScript does not have. And the name `fib` within the closure does resolve to the value of that variable from the containing scope; I don't know in what sense it doesn't.
kaya3
CC BY-SA 4.0
2024-04-02T03:48:37.763Z
Yes it does -- **every binding in javascript is letrec** -- that's just the way the langauge is defined.   And as I mentioned, handling letrec is not tough, particularly when it is just for a single symbol (the recrusive refs are not reference counted.)  My main point is **There's nothing special about closures**.  If you can handle anything else, you can handle closures the exact same way.
Chris Dodd
CC BY-SA 4.0
2024-04-02T03:49:03.813Z
@ChrisDodd You said *"explicit"*. You have already conceded that it is only implicit, so let's stop here.
kaya3
CC BY-SA 4.0
2024-04-02T03:51:59.707Z
@kaya: if it is explicit in the language specification, it is still explicit.
Chris Dodd
<h1>Swift</h1>
<h2>Explicit capture lists</h2>
<p>Swift closures can have <strong>explicit capture lists</strong>, which allow them to weakly capture variables to prevent strong references. By default, any variable referenced by a closure which is not in its capture list is strongly captured.</p>
<pre class="lang-swift prettyprint-override"><code>let foo: Foo
let bar: Bar
let baz: Baz
let qux: Qux

func returnAClosure() -&gt; () -&gt; Void {
    return { [foo, weak bar, unowned baz] in
        // `foo` is strongly captured.
        // It won't be deallocated as long as this closure is referenced somewhere.
        foo.doSomething()
        // `bar` is safely weakly captured.
        // Its type within the closure is nullable.
        // It can be deallocated while this closure is referenced, and if so, within the closure it will be set to `null`.
        bar?.doSomethingElse()
        // `baz` is unsafely weakly captured.
        // It can be deallocated while this closure is referenced, and if so, it will point to garbage data, causing undefined behavior if the closure is invoked.
        baz.doSomethingElse2()
        // Variables not explicitly specified in capture lists default to being strongly captured.
        // So `qux` is strongly captured like `foo`.
        // Note that, while identical when capturing reference types,
        //   an explicit capture and implicit capture have different behavior when capturing value types like `struct`s (see the official Swift documentation).
        qux.doSomethingElse3()
    }
}
</code></pre>
<p>See <a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/expressions/#Capture-Lists" rel="nofollow noreferrer">the official Swift documentation</a> <a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting/#Resolving-Strong-Reference-Cycles-for-Closures" rel="nofollow noreferrer">(2)</a> and <a href="https://www.hackingwithswift.com/articles/179/capture-lists-in-swift-whats-the-difference-between-weak-strong-and-unowned-references" rel="nofollow noreferrer">this article</a> for more info.</p>
<h2>Make all captured variables explicit</h2>
<p>Swift also has a special rule that <em><strong>escaping closures</strong> can't reference the methods or properties of <code>self</code> without explicitly qualifying them or including <code>self</code> in the explicit capture list</em>. Escaping closures are those that may continue to exist after the scope they are bound in (e.g. are assigned to a field or global variable or returned by a function); non-escaping closures can't create strong cycles, so this special rule doesn't apply to them. A subtle problem that arises with escaping closures is that, without this special rule, they could capture <code>self</code> without literally referring to <code>self</code>, since ordinarily Swift allows a class to refer to its own methods and properties without the <code>self</code> qualifier. The rule effectively makes it so a closure will only directly capture variables which are literally referenced somewhere in its body, although those variables may still have their own references which the closure transitively upholds.</p>
<p>The rule doesn't do anything more than require the programmer to literally include <code>self</code> in the closure; it doesn't change Swift's semantics or expressiveness, and doesn't actually prevent strong cycles between <code>self</code> and the closure. Presumably it's an attempt by the language designers to make programmers more aware when they capture <code>self</code>, and nudge them towards weakly capturing <code>self</code>, while still allowing them to strongly capture if necessary. I can't speak towards what motivated the Swift developers to include the rule, or its effectiveness at preventing strong reference cycles vs the amount of strong reference cycles involving closures that remain in Swift code.</p>
<p>See <a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/#Escaping-Closures" rel="nofollow noreferrer">the &quot;Escaping Closures&quot; section in the official Swift documentation</a> for more info.</p>

CC BY-SA 4.0
2024-04-02T03:35:16.800Z
2024-04-02T03:41:03.937Z
2024-04-02T03:41:03.937Z
tarzh
# How do languages with only reference counting deal with closures?
Posted by: username_0 on 2024-04-01
Reference counting works best if there are no cycles. But closures that allow access to every variable in the parent scope by default automatically create cycles.

There are obvious solutions like only importing actually used or previously defined variables. There are also more advanced solutions like considering it like a member method and extend the lifetime of the parent only in that way i.e. using the same reference counter as the parent scope.

But I want to know the possibilities and varieties, and see whether there are more innovative ways.
**Tags:** garbage-collection closure
> **Comments:**
> **username_1**: I think generally, regardless of the problem of reference cycles, any implementation of closures which cares about avoiding memory leaks will not retain local variables that aren't closed over; even if those references are cyclic, they are inaccessible, and retaining them would cause some garbage to be uncollectible. So what you describe as *"only import[ing] actually used ... variables"* is something we should assume about every implementation, unless garbage collection isn't a concern at all (in which case there is no question to answer).  
> **username_1**: Besides that, you could equally ask how languages with only reference counting deal with reference cycles in other objects that aren't closures. There are some interesting answers which aren't specific to the issue of closures, but which presumably also address the problem of recursive closures.  
> **username_0**: "Even if those references are cyclic, they are inaccessible". A reasonable point. Why didn't I think of that... But there is [a question asking for closures with mutual recursion](https://langdev.stackexchange.com/q/1682/1149). Combined with that it will still generate reference cycles. About answers not specific to closures, I don't know how to change the question to cover them, or whether I should without seeing how similar they are.  
> **username_1**: Off the top of my head, the most common approach is to periodically check for cycles (not sure if this counts as "only reference counting"), or some languages just let reference cycles be memory leaks. [Lobster](https://aardappel.github.io/lobster/memory_management.html) is interesting, because it doesn't collect cycles, but programs run in debug mode issue a "cycle report" upon termination, giving information the programmer can use to break those cycles in their data structures (so that reference counting will be enough). Not specific to closures, but I think most approaches won't be.  
> **username_2**: One day a student came to Moon and said: "I understand how to make
a better garbage collector.  We must keep a reference count of the
pointers to each cons."

Moon patiently told the student the following story:

     "One day a student came to Moon and said: `I understand how to
     make a better garbage collector...  
> **username_2**: I think if you are limited to *only* reference counting, cyclic structures are inherently uncollectable, and closures aren't specifically different in that way in either making or being part of cycles. Is there something specific you're thinking of that motivates this framing (e.g. you have in mind a particular existing language designed with RC+special closure treatment, but aren't naming it)?  
> **username_0**: @kaya3 I'm more interested in the directions like weak references, that could be useful to many practical cases, though not solving everything. I'm more interested in allowing immediate destructors, than efficiency, memory leaks, etc, for which another backup garbage collector seem better.  
> **username_0**: @MichaelHomer Actually I have listed a solution in the question, to use the same reference counter as the parent scope. (On this direction it ultimately would be static analysis of strongly connected components, which does work perfectly for a subdomain of the problem.) I haven't write code for garbage collection. See also the previous comment.  
> **username_3**: " But closures that allow access to every variable in the parent scope by default automatically creates cycles."  Why?  Only if you can inject a reference to the closure into the parent scope.  But if you don't allow mutable bindings, there's no reason (and no way) to do that.  You can only get recusive bindings with an explicit `letrec` construct, and then you ensure all the mutaully recusive objects share a single reference count, and the internal refs between them are not reference counted.  
> **username_1**: @ChrisDodd "Every variable in the parent scope" includes the one which refers to the closure, at least if it's a named closure. Anonymous closures wouldn't have that issue. But there are lots of languages which allow mutable bindings and don't require `letrec`.  
> **username_4**: Swift uses weak references, and closures can declare a capture list. See https://docs.swift.org/swift-book/documentation/the-swift-programming-language/automaticreferencecounting#Strong-Reference-Cycles-for-Closures  
> **username_3**: @kaya3: Mutable bindings can lead to cycles that refcounting has problems with -- there's nothing special or different about closures.  Absent  mutable bindings, the newly created closure is bound in a new scope, not in the parent scope, so there's no cycles.  So if you don't allow mutable bindings and dont allow recursive binding (no letrec equivalent), then there are no cycles and closures are no different from any other object.  Even with letrec, you can handle that specially (basically, a single refcount for all the recusively bound things) and avoid cycles that way.  
> **username_1**: @ChrisDodd In JavaScript, `const fib = x => n >= 2 ? fib(n-1) + fib(n-2) : n;` is a closure which closes over the local variable `fib`, which holds a reference to the closure. This is created without any mutable bindings and without a `letrec` keyword. This contradicts your statement that *"if you don't allow mutable bindings, [...] You can only get recusive bindings with an explicit `letrec` construct"*. Nonetheless, an answer which excludes the possibility of mutable bindings or recursion without `letrec` is not a very general answer, since that excludes so many languages.  
> **username_3**: @kaya3: That's an example of a letrec (even though it does not use that keyword), as the definition of fib used in the binding is recursive, not the definition from the containing scope.  Javascript, like many langauges, makes all bindings implicitly letrec.  
> **username_1**: @ChrisDodd You said *"explicit `letrec` construct"*, which JavaScript does not have. And the name `fib` within the closure does resolve to the value of that variable from the containing scope; I don't know in what sense it doesn't.  
> **username_3**: Yes it does -- **every binding in javascript is letrec** -- that's just the way the langauge is defined.   And as I mentioned, handling letrec is not tough, particularly when it is just for a single symbol (the recrusive refs are not reference counted.)  My main point is **There's nothing special about closures**.  If you can handle anything else, you can handle closures the exact same way.  
> **username_1**: @ChrisDodd You said *"explicit"*. You have already conceded that it is only implicit, so let's stop here.  
> **username_3**: @kaya: if it is explicit in the language specification, it is still explicit.  
---
## 1 answers
### Answer by username_5 on 2024-04-02. Score: 3
Swift
Explicit capture lists
Swift closures can have explicit capture lists, which allow them to weakly capture variables to prevent strong references. By default, any variable referenced by a closure which is not in its capture list is strongly captured.
let foo: Foo
let bar: Bar
let baz: Baz
let qux: Qux

func returnAClosure() -> () -> Void {
    return { [foo, weak bar, unowned baz] in
        // `foo` is strongly captured.
        // It won't be deallocated as long as this closure is referenced somewhere.
        foo.doSomething()
        // `bar` is safely weakly captured.
        // Its type within the closure is nullable.
        // It can be deallocated while this closure is referenced, and if so, within the closure it will be set to `null`.
        bar?.doSomethingElse()
        // `baz` is unsafely weakly captured.
        // It can be deallocated while this closure is referenced, and if so, it will point to garbage data, causing undefined behavior if the closure is invoked.
        baz.doSomethingElse2()
        // Variables not explicitly specified in capture lists default to being strongly captured.
        // So `qux` is strongly captured like `foo`.
        // Note that, while identical when capturing reference types,
        //   an explicit capture and implicit capture have different behavior when capturing value types like `struct`s (see the official Swift documentation).
        qux.doSomethingElse3()
    }
}

See the official Swift documentation (2) and this article for more info.
Make all captured variables explicit
Swift also has a special rule that escaping closures can't reference the methods or properties of self without explicitly qualifying them or including self in the explicit capture list. Escaping closures are those that may continue to exist after the scope they are bound in (e.g. are assigned to a field or global variable or returned by a function); non-escaping closures can't create strong cycles, so this special rule doesn't apply to them. A subtle problem that arises with escaping closures is that, without this special rule, they could capture self without literally referring to self, since ordinarily Swift allows a class to refer to its own methods and properties without the self qualifier. The rule effectively makes it so a closure will only directly capture variables which are literally referenced somewhere in its body, although those variables may still have their own references which the closure transitively upholds.
The rule doesn't do anything more than require the programmer to literally include self in the closure; it doesn't change Swift's semantics or expressiveness, and doesn't actually prevent strong cycles between self and the closure. Presumably it's an attempt by the language designers to make programmers more aware when they capture self, and nudge them towards weakly capturing self, while still allowing them to strongly capture if necessary. I can't speak towards what motivated the Swift developers to include the rule, or its effectiveness at preventing strong reference cycles vs the amount of strong reference cycles involving closures that remain in Swift code.
See the "Escaping Closures" section in the official Swift documentation for more info.
---
