# Function inside struct allocates when referenced

**URL:** https://discourse.julialang.org/t/function-inside-struct-allocates-when-referenced/105785
**Category:** New to Julia
**Tags:** function
**Created:** [November 4, 2023, 4:55am UTC](https://discourse.julialang.org/t/function-inside-struct-allocates-when-referenced/105785 "2023-11-04T04:55:37Z")
**Posts on this page:** 1
**Showing post:** 22

<div class="post-metadata">

### Author: ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)
#### Post date: [November 7, 2023, 2:02pm UTC](https://discourse.julialang.org/t/function-inside-struct-allocates-when-referenced/105785/22 "2023-11-07T14:02:03Z")

</div>

> [@abraemer](#):
>
> If all function have the same signature, then ideally we could communicate this to Julia and then Julia could treat the functions just as something like a function pointer which it blindly follows.

FunctionWrappers is not this blind, it safeguards the types. The call signature restriction parametizes the wrapper with the _intended_ return type and argument types, and the wrapper constructor takes a function as an argument.

1. Taking the function as an argument is almost self-explanatory, we are trying to group function calls together in a language where functions don’t have fixed input types and return types. So, a concrete wrapper type constructor must take any function as an input.

2. Fixing the return type provides type stability of the functions’ output, which is the bare minimum of categorizing functions in statically typed languages. Since there’s no guarantee of type stability of 1 method, let alone several functions, a `convert` step of the return value is added after calling the wrapped function. This accommodates type-unstable methods, but a `convert` with an uninferred input would need a runtime dispatch so it’s best to stick to type-stable methods if you’re going this far to avoid runtime dispatches and allocations.

3. Fixing the argument types provides the rest of the necessary information to dispatch and compile a function call given the wrapped function, and the wrapper stores the compiled code to skip over the typical dispatch mechanism. A `convert` step of the input arguments is also added before calling the wrapped function. (Hypothetically, function calls could be grouped by return type alone so the argument types could be a field instead of parameters of the wrapper type, but it seems a little crazy to micromanage that for every element of an array of call signatures only to probably input the same argument types every iteration.)

So a FunctionWrapper incurs a runtime cost to make sure what goes in and out of the wrapped compiled code is type-safe, though several `convert`s are usually cheaper than a runtime dispatch. EDIT: those `convert`s might be no-ops if the compiler infers the inputs already are the target type. Also the stored compiled code is not updated when the original method is edited, so use `reinit_wrapper` on existing instances or replace them entirely.

I’ve never used it, but there is a package FunctionWranglers.jl that doesn’t incur this cost. Rather than wrapping a function one by one, it takes in entire arrays of functions and uses recursively inlined generated functions to unroll loops over them in a set of higher order functions. Think the if-statements checking the function in Variant 4, but the if-statements check the _index_ so the same function at different indices still get their own branch. I’ve never reached for this because the `map`-like function requires the same input values for each call, indexing the wrangled array isn’t constant time (again, massive unrolled loop), and you can forget about any array mutations after it gets wrangled into recursive immutable `struct` instances. The repository hasn’t been touched for a couple years but I’m guessing it works because the package has no dependencies and I haven’t spotted any internal or unstable features in the short source file.

---

_[View the full topic](https://discourse.julialang.org/t/function-inside-struct-allocates-when-referenced/105785)._
