# Again on closures and type instability

**URL:** <https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664>\
**Category:** Performance\
**Tags:** type-stability, closure\
**Created:** [December 11, 2020, 1:56pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664 "2020-12-11T13:56:18Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 11, 2020, 1:56pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664/1 "2020-12-11T13:56:18Z")

</div>

Consider the simple functions:

```julia
inner(x,a) = a*x
outer(f,x) = f(x)

```

If one calls `outer` using a closure and global, non-constant parameter `a` , we have a type-instability:

```julia
julia> a = 5; x = 2;

julia> @code_warntype outer( x -> inner(x,a), x)
Variables
  #self#::Core.Compiler.Const(outer, false)
  f::Core.Compiler.Const(var"#5#6"(), false)
  x::Int64

Body::Any
1 ─ %1 = (f)(x)::Any
└── return %1

```

This is solved by declaring `a` constant or wrapping the call to `outer` into a function which, by itself, receives `a` as a parameter, i. e. `f(x,a) = outer(x->inner(x,a),x))`.

Yet, from a non-specialist point of view, these alternatives should not be necessary if the parsing of `outer(x->inner(x,a),x)` translated directly to that, or to something like:

```julia
function outer2(a,x)
  clos = x -> inner(a,x)
  outer(clos,x)
end

```

That seems to be possible, since the anonymous function defined as a parameter cannot change, that is, it seems to be as constant as any other data passed to the `outer` function which are constant from the point of view of the function even if they are non-constant in the global scope. The function then would specialize to the input parameters of `inner` as well.

Is there a fundamental reason for that not being possible (or simple?)

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 11, 2020, 2:02pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664/2 "2020-12-11T14:02:27Z")

</div>

The `x -> inner(x,a)` get evaluated (in the scope containing `f`) before it gets passed into `outer`. That is always the case, e.g.:

```julia
julia> a,b = 1,2
(1, 2)

julia> f(x) = x
f (generic function with 1 method)

julia> f(a + b)
3

```

there `a+b` gets evaluated first and then it’s passed to `f`. The same occurs in the case of the anonymous function and thus it binds a non-const global. This cannot be changed willy-nilly.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 11, 2020, 2:04pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664/3 "2020-12-11T14:04:47Z")

</div>

> [@mauro3](#):
>
> This cannot be changed willy-nilly.

Any idea if that is because of a technical difficulty, or if that behavior is desirable for some reason, or if it is because it would brake anything?

Edit: Now I see that your example, with two parameters, indicated that changing that would brake a lot of things… A very specific parsing of the arguments and of the closure would be needed.

Edit2: My “solution” button disappeared 😬

---

<div class="post-metadata">

**Author:** ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)\
**Post date:** [December 11, 2020, 3:19pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664/4 "2020-12-11T15:19:33Z")

</div>

> [@lmiq](#):
>
> Edit2: My “solution” button disappeared

I think in certain categories there are no “solutions”. Not sure though.

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 11, 2020, 5:55pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664/5 "2020-12-11T17:55:06Z")

</div>

I am writing some of the things I learn here in this docs and sharing with some students, and I have written a section on closures now, incorporating what I have learnt here:

[https://m3g.github.io/JuliaCookBook.jl/stable/closures/](https://m3g.github.io/JuliaCookBook.jl/stable/closures/)

The section on closures of the manual ([Julia Functions · The Julia Language](https://docs.julialang.org/en/v1/devdocs/functions/#Closures)) is very succinct, so this may be useful for others. If someone happens to read that and finds errors, please let me know.

---

<div class="post-metadata">

**Author:** ![mbauman](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mbauman/32/31082_2.png) [@mbauman](https://discourse.julialang.org/u/mbauman)\
**Post date:** [December 11, 2020, 6:04pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664/6 "2020-12-11T18:04:28Z")

</div>

There’s nothing really particular to closures here. In your example `a` is a global. Don’t use non-constant globals if you care about performance.

```julia
julia> a = 5; x = 2;
julia> @code_warntype outer( x -> inner(x,a), x)

```

If you do this in a local scope, all is well:

```julia
julia> inner(x,a) = a*x
inner (generic function with 1 method)

julia> outer(f,x) = f(x)
outer (generic function with 1 method)

julia> function doit()
           a = 5; x = 2;
           return outer( x -> inner(x,a), x)
       end
doit (generic function with 1 method)

julia> doit()
10

julia> @code_warntype doit()
Variables
  #self#::Core.Compiler.Const(doit, false)
  #1::var"#1#2"{Int64}
  a::Int64
  x::Int64

Body::Int64

```

(edit: I also just enabled solutions on this category)

---

<div class="post-metadata">

**Author:** ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)\
**Post date:** [December 11, 2020, 6:10pm UTC](https://discourse.julialang.org/t/again-on-closures-and-type-instability/51664/7 "2020-12-11T18:10:58Z")

</div>

> [@mbauman](#):
>
> There’s nothing really particular to closures here. In your example `a` is a global. Don’t use non-constant globals if you care about performance

It was not completely clear to me the scope in which the closure, inside a function call, could be evaluated. The previous answer made that clear to me.
