# What are Opaque Closures?

**URL:** https://discourse.julialang.org/t/what-are-opaque-closures/60006
**Category:** General Usage
**Tags:** question
**Created:** [April 25, 2021, 9:45pm UTC](https://discourse.julialang.org/t/what-are-opaque-closures/60006 "2021-04-25T21:45:50Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![suavesito](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/suavesito/32/34386_2.png) [@suavesito](https://discourse.julialang.org/u/suavesito)
#### Post date: [April 25, 2021, 9:45pm UTC](https://discourse.julialang.org/t/what-are-opaque-closures/60006/1 "2021-04-25T21:45:50Z")

</div>

In Slack there was a [question](https://julialang.slack.com/archives/C67910KEH/p1619311934178800?thread_ts=1619276549.161100&cid=C67910KEH) about opaque closures. I found that what I was assuming they were is not the real thing, they are not closures that pass variables as value… so here I post the answer (thanks to @oxinabox) and a [link](https://julialang.slack.com/archives/C67910KEH/p1619342841192300?thread_ts=1619276549.161100&cid=C67910KEH) to the original comment so it can be more visible.

> As I understand it.  
> This is **not** true \[1\]. They do not do that.

> Opaque closures are closures that make no promises about what is inside them.

> Normal closures promise to carry references to every variable that is used inside them (and nothing else), and to run exactly the code inside them when they are called. Including respecting newly created or overwritten methods.

> Opaque closures on the other hand relax the requirements, and basically just promise to perform something equivalent in behaviour to their body. Except they always run in the world age they were created, so they don’t observe new methods that were added (this makes them very unfriendly for interactive use, but like @pure they are not really intended for normal use).  
> What this allows them to do is move computation that depends only on variables in the parent scope (and not on the closures inputs) out of the closure and into the parent scope so they run when the closure is created (and then that result is closed over). This in turn makes them much more optimizable as the optimizer can optimize the (parts of) the closure body and the parent function together.

> **This has nothing to do with capture by name or capture by value.**

* * *

1. That they pass variables as value.

---

<div class="post-metadata">

### Author: ![goretkin](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/goretkin/32/167_2.png) [@goretkin](https://discourse.julialang.org/u/goretkin)
#### Post date: [April 26, 2021, 3:32pm UTC](https://discourse.julialang.org/t/what-are-opaque-closures/60006/2 "2021-04-26T15:32:17Z")

</div>

> [@suavesito](#):
>
> [normal closures] promise […] to run exactly the code inside them when they are called.  
> [opaque closures] promise to perform something equivalent in behaviour to their body

I would like to better understand this point, so I tried to make an example.

```julia
function make_closure(y)
    foo(x) = x + 1

    function closure(x)
        foo(x) * y
    end

    return (foo, closure)
end

(foo, f) = make_closure(2)

```

```julia
julia> f(2)
6

julia> f(2.0)
6.0

julia> foo(x::Float64) = x + 1.25
ERROR: cannot define function foo; it already has a value
Stacktrace:
 [1] top-level scope
   @ none:0

julia> f.foo(x::Float64) = x + 1.25

julia> f(2)
6

julia> f(2.0)
6.5

```

So the closure `f` was sensitive to the new method added to `foo`. I’m not sure why it is not the case, but I did expect it to be possible to define a new method on the `foo` returned by `make_closure`.

It sounds like opaque closures would not allow

```julia
julia> f.foo
foo (generic function with 2 methods)

julia> f.y
2

```

which, from memory, is undocumented behavior anyway. Is there a better example to try to illustrate the distinction?

---

<div class="post-metadata">

### Author: ![WschW](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/wschw/32/6575_2.png) [@WschW](https://discourse.julialang.org/u/WschW)
#### Post date: [April 26, 2021, 3:56pm UTC](https://discourse.julialang.org/t/what-are-opaque-closures/60006/3 "2021-04-26T15:56:15Z")

</div>

None of those are opaque closures.

opaque closures can be made by putting `@opaque` in front of them.

[https://github.com/JuliaLang/julia/blob/ca2332e868d24115dd8a75b80fde31eb1f9880fe/base/opaque\_closure.jl](https://github.com/JuliaLang/julia/blob/ca2332e868d24115dd8a75b80fde31eb1f9880fe/base/opaque_closure.jl)
