# Functors and allocations

**URL:** <https://discourse.julialang.org/t/functors-and-allocations/62547>\
**Category:** New to Julia\
**Tags:** memory-allocation, functions, functors\
**Created:** [June 7, 2021, 8:09pm UTC](https://discourse.julialang.org/t/functors-and-allocations/62547 "2021-06-07T20:09:51Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![vettert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vettert/32/30599_2.png) [@vettert](https://discourse.julialang.org/u/vettert)\
**Post date:** [June 7, 2021, 8:09pm UTC](https://discourse.julialang.org/t/functors-and-allocations/62547/1 "2021-06-07T20:09:51Z")

</div>

I would like define a custom type carrying parameters for a function inside it and then I would like to update the parameters of the function. The problem is that I don’t know the number of parameters a priori (it shall be user-selectable).

In the code below, I am using a “functor” for this (with an example function using two parameters…this part would also be up for the user to change). I am not sure this is the right way 🙂 Any tips?

Also, is there a way to avoid the allocation in “bench1”? Am I benchmarking it correctly? “bench2” is of course just updating a vector and does not allocate; that makes sense to me.

Here is the MWE:

```julia
module atest

struct foo{T<:Real}
    functionparameters::Vector{T}
end

mutable struct modelparameters
    bar::foo
    barbar::Vector{Float64}
end

function (f::foo)(x)
    f.functionparameters[1]*(x-1)^f.functionparameters[2]
end

end

a = atest.modelparameters(atest.foo([1e-6, 1]), [1.0, 2.0])
bench1 = @benchmark $a.bar = $(atest.foo)($[2e-6, 2])
bench2 = @benchmark $a.barbar = $[2.0, 3.0]

```

bench1:

```julia
BenchmarkTools.Trial:
  memory estimate: 16 bytes
  allocs estimate: 1
  --------------
  minimum time: 7.708 ns (0.00% GC)
  median time: 8.609 ns (0.00% GC)
  mean time: 11.344 ns (4.81% GC)
  maximum time: 2.183 μs (98.23% GC)
  --------------
  samples: 10000
  evals/sample: 999

```

bench2:

```julia
BenchmarkTools.Trial:
  memory estimate: 0 bytes
  allocs estimate: 0
  --------------
  minimum time: 2.400 ns (0.00% GC)
  median time: 2.800 ns (0.00% GC)
  mean time: 3.023 ns (0.00% GC)
  maximum time: 36.300 ns (0.00% GC)
  --------------
  samples: 10000
  evals/sample: 1000

```

edit: made the MWE hopefully clearer.

---

<div class="post-metadata">

**Author:** ![Vasily\_Pisarev](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vasily_pisarev/32/7929_2.png) [@Vasily\_Pisarev](https://discourse.julialang.org/u/Vasily_Pisarev)\
**Post date:** [June 7, 2021, 9:11pm UTC](https://discourse.julialang.org/t/functors-and-allocations/62547/3 "2021-06-07T21:11:34Z")

</div>

> [@vettert](#):
>
> is there a way to avoid the allocation in “bench1”?

`foo` is an abstract type.  
To avoid the allocation, set the type of `modelparameters.bar` to `foo{Float64}` or parameterize the `modelparameters` type.

---

<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:** [June 8, 2021, 12:35am UTC](https://discourse.julialang.org/t/functors-and-allocations/62547/4 "2021-06-08T00:35:01Z")

</div>

> [@vettert](#):
>
> I would like define a custom type carrying parameters for a function inside it. The problem is that I don’t know the number of parameters a priori (it shall be user-selectable).

Note that you can just use a closure for this. That way the user can pass any parameters they want and you don’t need to know the number or types of these parameters, and you don’t need to require the user to use a special “functor” type.

For example:

```julia
# ≈ ∫ₐᵇf(x)dx
function myintegral(f, a, b, N=100)
    x = range(a,b, length=N+1)[1:end-1]
    return sum(f, x) * step(x) # N-point left Riemann sum
end

# call myintegral, wrapping some parameters into a closure:
someparameter1 = 7
someparameter2 = π
approx_integral = myintegral(x -> cos(someparameter2 * x - someparameter1), 0, 1, 10^4)

# compute the error:
exact_integral = (sin(someparameter2 * 1 - someparameter1) + sin(someparameter1)) / someparameter2
@show approx_integral, exact_integral, abs(approx_integral - exact_integral) / abs(exact_integral)

```

---

<div class="post-metadata">

**Author:** ![vettert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vettert/32/30599_2.png) [@vettert](https://discourse.julialang.org/u/vettert)\
**Post date:** [June 8, 2021, 4:42am UTC](https://discourse.julialang.org/t/functors-and-allocations/62547/5 "2021-06-08T04:42:16Z")

</div>

Thanks! This has helped. For others looking this up in the future, here is the non-allocating version of this:

```julia
module atest

struct foo{T<:Real}
    functionparameters::Vector{T}
end

mutable struct modelparameters{T}
    bar::foo{T}
    barbar::Vector{Float64}
end

function (f::foo)(x)
    f.functionparameters[1]*(x-1)^f.functionparameters[2]
end

end

a = atest.modelparameters(atest.foo([1e-6, 1]), [1.0, 2.0])
bench1 = @benchmark $a.bar = $(atest.foo)($[2e-6, 2])
bench2 = @benchmark $a.barbar = $[2.0, 3.0]

```

---

<div class="post-metadata">

**Author:** ![vettert](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vettert/32/30599_2.png) [@vettert](https://discourse.julialang.org/u/vettert)\
**Post date:** [June 8, 2021, 5:04am UTC](https://discourse.julialang.org/t/functors-and-allocations/62547/6 "2021-06-08T05:04:04Z")

</div>

Thanks for your answer. I did originally use this approach, but as my code got more complex and I needed to pass around the user-defined function throughout the program (for example, it (and several other things) ends up getting passed as a parameter to a differential equation model), I ended up storing it in a struct for easier reference. This worked fine.

However, when I started doing things like minimizing an objective function by varying the parameters inside the closure, it started to become messy, because the type of the closure that I wanted to store changed when I re-defined it after the optimizer changed the parameters (I was still able to store it into my struct, but the field wasn’t type-specific anymore; I started disliking it…).

The above way with the functor is trying to get around this problematic. I am not sure yet, whether it is what I actually want, but I’ll find out soon enough!
