# Writing my own callbacks

**URL:** <https://discourse.julialang.org/t/writing-my-own-callbacks/92871>\
**Category:** General Usage\
**Created:** [January 12, 2023, 2:30pm UTC](https://discourse.julialang.org/t/writing-my-own-callbacks/92871 "2023-01-12T14:30:02Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![erlebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/erlebach/32/12973_2.png) [@erlebach](https://discourse.julialang.org/u/erlebach)\
**Post date:** [January 12, 2023, 2:30pm UTC](https://discourse.julialang.org/t/writing-my-own-callbacks/92871/1 "2023-01-12T14:30:02Z")

</div>

I thought I finally understood the various subtleties of scope and closure in Julia, but obviously not! Here is a self-contained MWE that demonstrates a callback that does not work and I do not know how to fix:

```julia
iter = 8

function callback(iter)
    println("callback: iter= ", iter)
end

cb2() = callback(iter)

function solver(; cb=callback)
    callback()
end

solver(; cb=cb2)

```

`iter` is a variable at global scope. I get the error message when executing the last line:

```julia
ERROR: UndefVarError: iter not defined
Stacktrace:
 [1] callback()
   @ Main ~/src/2022/rude/giesekus/test_global.jl:30
 [2] solver(; cb::Function)
   @ Main ~/src/2022/rude/giesekus/test_global.jl:40
 [3] top-level scope
   @ ~/src/2022/rude/giesekus/test_global.jl:44

```

which seems rather straightforward.

I have defined the closure `cb2() = callback(iter)`, which I thought would capture the variable `iter`. When the callback is called from within `solver`, I expected `iter` inside `callback` to be visible, and yet it wasn’t. What is happening? Any insight is appreciated. Thanks.

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [January 12, 2023, 2:36pm UTC](https://discourse.julialang.org/t/writing-my-own-callbacks/92871/2 "2023-01-12T14:36:28Z")

</div>

> [@erlebach](#):
>
> ```julia
> function solver(; cb=callback)
> callback()
> end
> 
> ```

I think you want to call `cb()` here? With this change, I get:

```julia
julia> solver(; cb=cb2)
callback: iter= 8

```

---

<div class="post-metadata">

**Author:** ![erlebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/erlebach/32/12973_2.png) [@erlebach](https://discourse.julialang.org/u/erlebach)\
**Post date:** [January 12, 2023, 2:53pm UTC](https://discourse.julialang.org/t/writing-my-own-callbacks/92871/3 "2023-01-12T14:53:55Z")

</div>

Thank you! I just figured it out, returned to discourse, and you beat me to it! Thank you.

---

<div class="post-metadata">

**Author:** ![skleinbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/skleinbo/32/36080_2.png) [@skleinbo](https://discourse.julialang.org/u/skleinbo)\
**Post date:** [January 12, 2023, 2:54pm UTC](https://discourse.julialang.org/t/writing-my-own-callbacks/92871/4 "2023-01-12T14:54:12Z")

</div>

`cb2` is not a closure over `iter`. At least not in the sense I understand the term. It merely references `Main.iter` when called; it doesn’t capture it on declaration.

```julia
julia> cb()
callback: iter= 8

julia> iter = 7
7

julia> cb()
callback: iter= 7

```

In constrast, this will produce a closure.

```julia
julia> function makecb(iter)
         () -> callback(iter)
       end
makecb (generic function with 1 method)

julia> cb_closure = makecb(iter)
#3 (generic function with 1 method)

julia> cb_closure()
callback: iter= 7

julia> iter = 6
6

julia> cb_closure()
callback: iter= 7

```

Observe that `cb_closure` has a field `iter` in contrast to `cb2`.

```julia
julia> hasproperty(cb_closure, :iter)
true

julia> cb_closure.iter
7

```

---

<div class="post-metadata">

**Author:** ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)\
**Post date:** [January 12, 2023, 3:05pm UTC](https://discourse.julialang.org/t/writing-my-own-callbacks/92871/5 "2023-01-12T15:05:55Z")

</div>

Note that your original code doesn’t produce the error you reported, but “ERROR: MethodError: no method matching callback()” because of course the `callback` function is defined only with one argument, there isn’t any method with zero arguments…

---

<div class="post-metadata">

**Author:** ![erlebach](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/erlebach/32/12973_2.png) [@erlebach](https://discourse.julialang.org/u/erlebach)\
**Post date:** [January 12, 2023, 3:22pm UTC](https://discourse.julialang.org/t/writing-my-own-callbacks/92871/6 "2023-01-12T15:22:24Z")

</div>

Noted. Thanks for the addendum.
