# Passing a function as an argument via closure

**URL:** <https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017>\
**Category:** Performance\
**Tags:** question, package, performance, numerics, closure\
**Created:** [August 26, 2019, 10:56pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017 "2019-08-26T22:56:11Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![cpross90](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cpross90/32/10142_2.png) [@cpross90](https://discourse.julialang.org/u/cpross90)\
**Post date:** [August 26, 2019, 10:56pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/1 "2019-08-26T22:56:11Z")

</div>

I am creating some numerical methods, and I am running into some issues with closures.

Here’s an example of what I’m doing:

Function to drive myPkg:

```julia
function main()
    #allocate temporaries

    function linear()
        # Use temps and do stuff
    end

    function nonlinear()
        # Use temps and do stuff
    end

    myPkg.solver(retVal, linear, nonlinear, otherParams)

end

```

Function inside my module:

```julia
function solver(retval, linear, nonlinear, otherParams)
    for i = 1:N
        linear(retVal, otherParams)
        nonlinear(retVal, otherParams)
    end

    return retVal
end

```

My problem is that an excessive amount of allocations take place and the function is over ten times slower than if I encapsulate the functions inside of the module. I’m not certain if my concept of a closure is completely wrong, or if the way I have it causes additional temporaries to be created that I don’t see.

If you want a more concrete example checkout my GitHub for comparison of the module that encapsulates the functions ([https://github.com/cpross90/BenjaminOnoSolver.jl](https://github.com/cpross90/BenjaminOnoSolver.jl)) and the module that accepts external functions ([https://github.com/cpross90/SplitStep.jl](https://github.com/cpross90/SplitStep.jl)). I’m looking to have the module work similarly to how the Optim.jl package receives objective functions for a cost function/gradient/hessian.

If there are any suggestions to how I can tackle this better I am all ears. Just an undergraduate applied math researcher trying to get a hold of Julia.

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:** [August 26, 2019, 11:39pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/2 "2019-08-26T23:39:21Z")

</div>

> [@cpross90](#):
>
> My problem is that an excessive amount of allocations take place and the function is over ten times slower than if I encapsulate the functions inside of the module.

You could be running into [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276) … try defining any captured variables in a `let` block as described in that issue.

---

<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:** [August 27, 2019, 12:53pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/3 "2019-08-27T12:53:45Z")

</div>

Here’s a concrete example of what @stevengj is describing:

```julia
julia> function solver(f)
         minimum(f, 1:10)
       end
solver (generic function with 1 method)

julia> function slow()
         # allocate temporaries
         x = 1
         
         # define inner function
         function inner(y)
           x = y
           y
         end
         
         solver(inner)
       end
slow (generic function with 1 method)

```

The telltale sign of issue 15276 is the `Core.Box` in `@code_warntype`:

```julia
julia> @code_warntype slow()
Body::Int64
1 ─ %1 = %new(Core.Box)::Core.Box
│ (Core.setfield!)(%1, :contents, 1)
│ %3 = %new(Main.:(#inner#12), %1)::getfield(Main, Symbol("#inner#12"))
│ %4 = Base.min::typeof(min)
│ %5 = invoke Base._mapreduce(%3::getfield(Main, Symbol("#inner#12")), %4::typeof(min), $(QuoteNode(IndexLinear()))::IndexLinear, $(QuoteNode(1:10))::UnitRange{Int64})::Int64
└── return %5

```

We can fix this by using a `Ref`, like so:

```julia
julia> function fast1()
         x = Ref(1)
         
         function inner(y)
           x[] = y
           y
         end
         
         solver(inner)
       end
fast1 (generic function with 1 method)

julia> @code_warntype fast1()
Body::Int64
1 ─ %1 = %new(Base.RefValue{Int64}, 1)::Base.RefValue{Int64}
│ %2 = %new(getfield(Main, Symbol("#inner#14")){Base.RefValue{Int64}}, %1)::getfield(Main, Symbol("#inner#14")){Base.RefValue{Int64}}
│ %3 = Base.min::typeof(min)
│ %4 = invoke Base._mapreduce(%2::getfield(Main, Symbol("#inner#14")){Base.RefValue{Int64}}, %3::typeof(min), $(QuoteNode(IndexLinear()))::IndexLinear, $(QuoteNode(1:10))::UnitRange{Int64})::Int64
└── return %4

```

or using a `let` block as described in [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276)

---

<div class="post-metadata">

**Author:** ![jlperla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlperla/32/34332_2.png) [@jlperla](https://discourse.julialang.org/u/jlperla)\
**Post date:** [August 27, 2019, 1:21pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/4 "2019-08-27T13:21:54Z")

</div>

As a general coding pattern to teach to people, do you always avoid this issue with 100% certainty if you have a closure over a `struct`, `Tuple` or a `NamedTuple`?

---

<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:** [August 27, 2019, 1:56pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/5 "2019-08-27T13:56:02Z")

</div>

I’m not sure exactly what you mean, but I think the answer is no: the issue is just as likely to occur with a struct as with an `Int`.

---

<div class="post-metadata">

**Author:** ![jlperla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlperla/32/34332_2.png) [@jlperla](https://discourse.julialang.org/u/jlperla)\
**Post date:** [August 27, 2019, 4:38pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/6 "2019-08-27T16:38:08Z")

</div>

Well, with the “Global scope debacle” things are different for immutables from vectors, etc. The issue is that a name binding changes above in the

```julia
 function inner(y)
           x = y
           y
         end

```

function. This means that the compiler has a lot of trouble determining types because it knows the names are rebound. I guess the essence of my quetsion is: if you avoid changes in the named bindings, then does [performance of captured variables in closures · Issue #15276 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/15276) bind in practice?

---

<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:** [August 27, 2019, 4:46pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/7 "2019-08-27T16:46:16Z")

</div>

> [@jlperla](#):
>
> Well, with the “Global scope debacle” things are different for immutables from vectors, etc.

You mean that assignment (`a = ...`) is different from mutation (`foo!(a)`)?

Anyway, avoiding rebinding variables that are closed over can help with that issue, yes.

---

<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:** [August 27, 2019, 4:48pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/8 "2019-08-27T16:48:35Z")

</div>

A `let` block is necessary when you see a `Core.Box` around a variable which is read but whose binding does not change. If you need to rebind a variable, then you can instead use a `Ref` and mutate that `Ref`. My general experience has been that the first issue (Boxing of variables which are not re-bound) is less common now, but the second issue (Boxing of variables whose bindings need to change) is still likely.

---

<div class="post-metadata">

**Author:** ![jlperla](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jlperla/32/34332_2.png) [@jlperla](https://discourse.julialang.org/u/jlperla)\
**Post date:** [August 27, 2019, 4:55pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/9 "2019-08-27T16:55:08Z")

</div>

> [@rdeits](#):
>
> `let` block is necessary when you see a `Core.Box` around a variable which is read but whose binding does not change.

Yes. My issue is trying to come up with coding patterns for beginners to avoid this. They have enough trouble understanding basic scoping, and won’t be able to interpret warntype.

> [@rdeits](#):
>
> My general experience has been that the first issue (Boxing of variables which are not re-bound) is less common now

OK, that is helpful. When you say “less common”, any sense of the frequency? Assuming that you have a set of users who will never be able to reliably run `@code_warntype`, do you think they can safely avoid this in most cases these days if they don’t rebind? I think I can teach people not to rebind, as it is easy to visually parse the `x = ...`

---

<div class="post-metadata">

**Author:** ![cpross90](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cpross90/32/10142_2.png) [@cpross90](https://discourse.julialang.org/u/cpross90)\
**Post date:** [August 28, 2019, 5:09pm UTC](https://discourse.julialang.org/t/passing-a-function-as-an-argument-via-closure/28017/10 "2019-08-28T17:09:57Z")

</div>

Wow, this is awesome, thanks to everyone who’s left something here.

It appears that I might be having other type stability issues elsewhere. I’m not seeing anything in `@code_warntype` that would indicate type instability in the closure, so I’m going to comb through the module more carefully. This definitely helps give me a better idea of how to implement closures. Thanks again!
