# Is it possible to know if a function has captured local variables?

**URL:** <https://discourse.julialang.org/t/is-it-possible-to-know-if-a-function-has-captured-local-variables/128934>\
**Category:** General Usage\
**Tags:** function\
**Created:** [May 12, 2025, 9:18pm UTC](https://discourse.julialang.org/t/is-it-possible-to-know-if-a-function-has-captured-local-variables/128934 "2025-05-12T21:18:49Z")\
**Posts on this page:** 1\
**Showing post:** 10

<div class="post-metadata">

**Author:** ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)\
**Post date:** [May 13, 2025, 12:15am UTC](https://discourse.julialang.org/t/is-it-possible-to-know-if-a-function-has-captured-local-variables/128934/10 "2025-05-13T00:15:16Z")

</div>

It’s a subtle distinction at first, but a _closure_ is a narrower concept than simply a function referencing a variable from a parent scope. A closure is a function that does this _after the parent scope has expired_, and therefore needs to carry the variables with it as part of the function object.

This is not a closure:

```julia
a = Ref(1)
f(x) = x + a[]

```

This function doesn’t package anything extra, it’s just a regular function that happens to reference a global variable. Every time this function is called, it will dynamically look up the current value of `a` in the global scope, according to the normal rules of lexical scoping.

This is a closure:

```julia
g = let b = Ref(1)
    x -> x + b[]
end

```

Here, the lifetime of the variable `b` will have expired by the time `g` is assigned, since it was defined in the local scope started by `let` and ended by `end`. Thus, it’s up to `g` to keep `b` alive such that future calls still work. Therefore, a reference to `b` is stored as part of the `g` object. This is what a closure is: a function that comes packaged with one or more bindings from an expired scope. It’s actually just stored as a field. Try it yourself: `g.b[] == 1`. (This is an implementation detail, though, you shouldn’t rely on it.)

In contrast, there is no `f.a`. It’s not needed, since `a` is still alive and well in the global scope, such that `f` can reference it at any time.

This explains your observations. `f2 = deepcopy(f)` just gives you a function identical to `f`. In fact, since functions are immutable singletons, it will return `f` itself, such that `f2 === f`. The variable `a` is not involved, since there’s no reference from the object `f` to `a`.

In contrast, `g2 = deepcopy(g)` will recursively walk the `g` object, notice the reference to `b`, and make a copy of `b` and assemble a new function of the same type as `g` using the new copy of `b`. Thus, `g.b` and `g2.b` are not the same object, so mutating `g.b` does not change the behavior of `g2`, and vice versa.

Hope this helps!

---

_[View the full topic](https://discourse.julialang.org/t/is-it-possible-to-know-if-a-function-has-captured-local-variables/128934)._
