# Creating an anonymous function at the local level. Conflict with const resulting in performance issues

**URL:** <https://discourse.julialang.org/t/creating-an-anonymous-function-at-the-local-level-conflict-with-const-resulting-in-performance-issues/123921>\
**Category:** Performance\
**Created:** [December 17, 2024, 11:52am UTC](https://discourse.julialang.org/t/creating-an-anonymous-function-at-the-local-level-conflict-with-const-resulting-in-performance-issues/123921 "2024-12-17T11:52:45Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![stefkuypers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefkuypers/32/19185_2.png) [@stefkuypers](https://discourse.julialang.org/u/stefkuypers)\
**Post date:** [December 17, 2024, 11:52am UTC](https://discourse.julialang.org/t/creating-an-anonymous-function-at-the-local-level-conflict-with-const-resulting-in-performance-issues/123921/1 "2024-12-17T11:52:45Z")

</div>

I’m building a simulation framework and am running into the following problem:

I have a initialisation function init\_model(x::InitType) where x is a structure containing the information needed for initialisation of a model. In the init function I define an anonymous function that uses some data from x. What data is used and how many fields are used is dependant on the specific InitType.

When I use a regular anonymous function I get a huge performance hit, which is apparently due to the fact that the anonymous function is not a const by default. However, I can not use the const keyword in a function. How would I solve this in an elegant way without loosing the flexibility of the simulation framework.

Here’s the (simplified) code:

```julia
struct Model
  sim_function::Function
end

function run_simulation(model::Model, steps::Int)
  for i in 1:steps
    model.sim_function(i)
  end
end

abstract type Init end

struct InitType <: Init
  increment::Int
end

function increment_sim(x::Int, increment::Int)
  return x + increment
end

function init_model(init::InitType)
  # This does not compile. This is the problem.
  # It compiles without the const keyword but then performance goes out the window.
  const sim_function = x -> increment_sim(x, init.increment) 

  return Model(sim_function)
end

init = InitType(2)

run_simulation(init_model(init), 3)

```

EDIT: I don’t really understand why the const keyword is not allowed in a local context since it is perfectly possible to define a named function in the local scope of another function and since all named functions are const by default I’m guessing this should also be possible for anonymous functions?

---

<div class="post-metadata">

**Author:** ![nsajko](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nsajko/32/221187_2.png) [@nsajko](https://discourse.julialang.org/u/nsajko)\
**Post date:** [December 17, 2024, 12:10pm UTC](https://discourse.julialang.org/t/creating-an-anonymous-function-at-the-local-level-conflict-with-const-resulting-in-performance-issues/123921/2 "2024-12-17T12:10:06Z")

</div>

Two obvious issues before looking at this more closely:

> [@stefkuypers](#):
>
> `const sim_function = x -> increment_sim(x, init.increment)`

This doesn’t compile. Provide an actual MWE.

> [@stefkuypers](#):
>
> ```julia
> struct Model
> sim_function::Function
> end
> 
> ```

Consult the Performance Tips page in Julia’s Manual. In particular, `Function` is not a concrete type, so this is likely to cause horrible performance.

---

<div class="post-metadata">

**Author:** ![stefkuypers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefkuypers/32/19185_2.png) [@stefkuypers](https://discourse.julialang.org/u/stefkuypers)\
**Post date:** [December 17, 2024, 12:20pm UTC](https://discourse.julialang.org/t/creating-an-anonymous-function-at-the-local-level-conflict-with-const-resulting-in-performance-issues/123921/3 "2024-12-17T12:20:36Z")

</div>

I know the line with const does not compile. That is the problem. It compiles when I drop the const keyword but then my performance goes out the window.

The Function type does not cause (noticeable) performance issues if I use a named, and thus const, function.

---

<div class="post-metadata">

**Author:** ![foobar\_lv2](https://avatars.discourse-cdn.com/v4/letter/f/ee59a6/32.png) [@foobar\_lv2](https://discourse.julialang.org/u/foobar_lv2)\
**Post date:** [December 17, 2024, 12:57pm UTC](https://discourse.julialang.org/t/creating-an-anonymous-function-at-the-local-level-conflict-with-const-resulting-in-performance-issues/123921/4 "2024-12-17T12:57:18Z")

</div>

The problem is the interaction between your loop and struct definition:

```julia
struct Model
  sim_function::Function
end

function run_simulation(model::Model, steps::Int)
  for i in 1:steps
    model.sim_function(i)
  end
end

```

The method `run_simulation` is only compiled once, since all its argument types are concrete. So the compiled code has no clue what `sim_function` is.

There are two standard approaches:

First, you can make Model parametric, a la `struct Model{F<:Function} sim_function::F end`. Now `Model(identity)` and `Model((x)->x+1)` will have different types, and run\_simulation will be specialized to that type, permitting the compiler to statically dispatch and inline the thing.

This is sometimes inconvenient if you have code that needs to handle many different models with different sim\_function.

The second approach is to add a function barrier, a la

```julia
function run_simulation(model::Model, steps::Int)
  foreach(model.sim_function, 1:steps)
end

```

You should read the implementation – it is a one-liner `foreach(f, itr) = (for x in itr; f(x); end; nothing)`

Now you will have a dynamic dispatch to specialize `foreach` on the function. This specialized function runs the loop and needs no more dynamic dispatches. Hence, you only pay one dynamic dispatch, instead of `steps` many.

^this, i.e. dynamic multiple dispatch with full specialization on argument types and resultant techniques like well-placed function barriers, is really the unique claim-to-fame of the julia language.

I especially want to emphasize the advantages over e.g. to C++ template contortions on the one side, and e.g. the graalVM/JIT specialization algorithm on the other side. (oh, the contortions to avoid profile cross-pollution in JVM!)

The mechanism in julia is both human legible and convenient (but it does force a certain coding style, and it’s a bad match for some problem domains where e.g. java excels).

---

<div class="post-metadata">

**Author:** ![stefkuypers](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stefkuypers/32/19185_2.png) [@stefkuypers](https://discourse.julialang.org/u/stefkuypers)\
**Post date:** [December 17, 2024, 1:23pm UTC](https://discourse.julialang.org/t/creating-an-anonymous-function-at-the-local-level-conflict-with-const-resulting-in-performance-issues/123921/5 "2024-12-17T13:23:36Z")

</div>

Thanks!

I oversimplified the code though. The call to sim\_function happens deeper in the call stack, not at the top level in the iteration loop. So it’s within a function that is called within the iteration loop of the simulation.

I guess I’ll need to drop the anonymous function solution and store the data in the model (in the full implementation I can store arbitrary data in the model). I just found the anonymous function solution more elegant.
