# Modify variable in closure and type inference

**URL:** <https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765>\
**Category:** General Usage\
**Tags:** closure\
**Created:** [May 30, 2019, 12:55pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765 "2019-05-30T12:55:44Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [May 30, 2019, 12:55pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/1 "2019-05-30T12:55:44Z")

</div>

I would like to have a closure modify a captured variable. Here is a simple example:

```julia
function fancy_iteration(f::F, itr) where {F}
    for pt in itr
        f(pt)
    end
end

function mysum(f, itr)
    sum = 0.
    fancy_iteration(itr) do pt
        sum += f(pt)
    end
    sum
end

@code_warntype mysum(sin, ones(3))

```

Currently inference fails on this. Are the recommended workarounds?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [May 30, 2019, 4:41pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/2 "2019-05-30T16:41:49Z")

</div>

You can use a `Ref`, like this:

```julia
julia> function mysum(f, itr)
         sum = Ref(0.0)
         fancy_iteration(itr) do pt
           sum[] += f(pt)
         end
         sum[]
       end
mysum (generic function with 1 method)

```

---

<div class="post-metadata">

**Author:** ![dpsanders](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dpsanders/32/3573_2.png) [@dpsanders](https://discourse.julialang.org/u/dpsanders)\
**Post date:** [May 30, 2019, 4:46pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/3 "2019-05-30T16:46:42Z")

</div>

Why don’t you just return the new value from the function and modify the variable with the new value outside the function call?

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [May 31, 2019, 6:14am UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/4 "2019-05-31T06:14:25Z")

</div>

Wow that indeed works. I thought this would run into [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276), but it does not. Now I am confused. Can you comment on why this avoids 15276?

---

<div class="post-metadata">

**Author:** ![tkf](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tkf/32/17635_2.png) [@tkf](https://discourse.julialang.org/u/tkf)\
**Post date:** [May 31, 2019, 6:39am UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/5 "2019-05-31T06:39:40Z")

</div>

Any reason to not use `mapreduce`/`mapfoldl` for this?

---

<div class="post-metadata">

**Author:** ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)\
**Post date:** [May 31, 2019, 6:51am UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/6 "2019-05-31T06:51:47Z")

</div>

> [@jw3126](#):
>
> Wow that indeed works. I thought this would run into [https://github.com/JuliaLang/julia/issues/15276](https://github.com/JuliaLang/julia/issues/15276), but it does not. Now I am confused. Can you comment on why this avoids 15276?

You are no longer assigning to `sum` (you are just updating the content of the container) which means that there is no need to box the variable.

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [May 31, 2019, 6:53am UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/7 "2019-05-31T06:53:57Z")

</div>

Ah so 15276 only happens when I assign variables? I remember having problems with read only, too. But maybe that was fixed?  
Edit: Here is a read only example taken from [https://github.com/JuliaLang/julia/issues/15276#issuecomment-297596373](https://github.com/JuliaLang/julia/issues/15276#issuecomment-297596373)

```julia
julia> @noinline function call_func(f::Function)
           println(f())
       end
call_func (generic function with 1 method)

julia> # Simple version. `i` is a Box here.
       function log_loop(N, unlikely)
           s = 0
           for i=1:N
               s += i
               if unlikely
                   call_func(()->"asdf $i")
               end
           end
       end
log_loop (generic function with 1 method)

julia> @code_warntype log_loop(1, true) # fails to infer `i`

```

How is this different from

> [@Modify variable in closure and type inference](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/2):
>
> You can use a Ref, like this: julia\> function mysum(f, itr) sum = Ref(0.0) fancy\_iteration(itr) do pt sum[] += f(pt) end sum[] end mysum (generic function with 1 method)

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [May 31, 2019, 6:54am UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/8 "2019-05-31T06:54:57Z")

</div>

Yeah sure in this example one can even use the `sum` function. But the goal of the question is to be as close to the style of the example, while avoiding inference problems.

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [May 31, 2019, 3:40pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/9 "2019-05-31T15:40:52Z")

</div>

This seems to run into [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276) in more complicated situations. The following fails for me:

```julia
function fancy_iteration(f, itr)
    for pt in itr
        f(pt)
    end
end

function mysum2(f, itr)
    for i in 1:1
        sum = Ref(0.0)
        if true
            fancy_iteration(itr) do pt
                old = sum[]
                new = old + f(pt)
                sum[] = new
            end
        end
        return sum[]
    end
    error()
end

@code_warntype mysum2(sin, 1:3) #fails

```

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [May 31, 2019, 3:51pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/10 "2019-05-31T15:51:46Z")

</div>

> [@jw3126](#):
>
> @code\_warntype mysum2(sin, 1:3)

The traditional `let-block` workaround works just fine, though:

```julia
julia> function mysum2(f, itr)
           for i in 1:1
               sum = Ref(0.0)
               if true
                   let sum = sum
                       fancy_iteration(itr) do pt
                           old = sum[]
                           new = old + f(pt)
                           sum[] = new
                       end
                   end    
               end
               return sum[]
           end
           error()
       end

```

You can think of the `let` block as a really obvious promise to the compiler that _nothing_ inside the closure could possibly modify what `sum` is bound to in the outer scope.

---

<div class="post-metadata">

**Author:** ![jw3126](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jw3126/32/3086_2.png) [@jw3126](https://discourse.julialang.org/u/jw3126)\
**Post date:** [May 31, 2019, 4:10pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/11 "2019-05-31T16:10:47Z")

</div>

Thanks I also just tried that! Would you say that inference does well if I use let blocks + `Ref` for updating captured variables or are there other traps?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [May 31, 2019, 4:25pm UTC](https://discourse.julialang.org/t/modify-variable-in-closure-and-type-inference/24765/12 "2019-05-31T16:25:25Z")

</div>

Yes, that should work quite well as far as I know.
