# Question about Functors

**URL:** <https://discourse.julialang.org/t/question-about-functors/33876>\
**Category:** Performance\
**Tags:** functors\
**Created:** [January 27, 2020, 9:40pm UTC](https://discourse.julialang.org/t/question-about-functors/33876 "2020-01-27T21:40:59Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [January 27, 2020, 9:41pm UTC](https://discourse.julialang.org/t/question-about-functors/33876/1 "2020-01-27T21:41:00Z")

</div>

I am trying to solve an economic model. The algorithm involves an iterative two-step procedure, like a back-and-forth optimization. There are lots of inputs and moving parts. I created a `struct` to keep track of it all. What follows involves psuedocode rather than a MWE.

```julia
struct MyModel
A
B
C
D
end

```

The algorithm works like this: (1) holding `B` fixed, solve for new `A`, (2) holding new `A` fixed, solve for new `B`. Repeat. Each step takes as input potentially all fields of `MyModel` (and there many and of various types).

I created a functor that when called should initiate the algorithm and produce the solution (which is just `A` and `B` after convergence). However, inside that function I call functions that do each step of the algorithm – also in place.

```julia
function updateA!(m::MyModel)
# do stuff to get newA
# updates A in place (using Setfield.jl)
@set m.A = newA
return nothing
end

function updateB!(m::MyModel)
# do stuff to get newB
# updates B in place (using Setfield.jl)
@set m.B = newB
return nothing
end

```

So that the functor method actually is like this

```julia
function (m::MyModel)(;kw...)
chg = Inf
while chg > tolerance
   updateA!(m)
   updateB!(m)
   chg = ...
end
# A and B updated in place so returns nothing
return nothing
end

```

I am wondering what happens in this situation. Is it really using the same `m` object everywhere? Do I need to worry about unexpected behaviors here, which could be very very difficult to debug? I think of functors as operating on or within themselves (perhaps this is completely incorrect), so it feels weird to “pass” `m` to another mutating function as part of this process.

My initial goal of this approach was to keep the code clean, to eliminate unnecessary creation of temporary variables (eg. elements `C`, `D`, etc. are shared between the two steps), and ultimately to have this be performant. I am open to suggestions if this is a poor design decision.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [January 27, 2020, 10:44pm UTC](https://discourse.julialang.org/t/question-about-functors/33876/2 "2020-01-27T22:44:11Z")

</div>

That isn’t what Setfield.jl does.  
It doesn’t let you mutate immutable objects.  
It returns new objects with the given points updated.

e.g.

```julia
julia> using Setfield
[Info: Precompiling Setfield [efcf1570-3423-57d1-acb7-fd33fddbac46]

julia> struct Foo
       a
       b
       end

julia> foo1 = Foo(1,10)
Foo(1, 10)

julia> @set foo1.a=2
Foo(2, 10)

julia> foo1
Foo(1, 10)

```

So you can’t be returning `nothing`

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [January 27, 2020, 10:52pm UTC](https://discourse.julialang.org/t/question-about-functors/33876/3 "2020-01-27T22:52:36Z")

</div>

> [@tbeason](#):
>
> My initial goal of this approach was to keep the code clean, to eliminate unnecessary creation of temporary variables (eg. elements `C` , `D` , etc. are shared between the two steps), and ultimately to have this be performant. I am open to suggestions if this is a poor design decision.

This does not seem very nice.

The use of immutable datastructures come from the goal of mimimizing the amount of state you are keeping.  
State is hard to think about.  
So one tries to write code that only assigned each variable once, and never updates it.  
Updating a variable cases that same variable “means” something different in a different part of the code.  
Thus your code gets a implict depenence order, so you can’t move lines about without working out where state changes occur.  
Where as if you only assign each once, you can move lines about, but if you move them such that something isn’t assigned before it is used, you get an error.

Creation of temporary variables is cheap (free infact).  
It is the allocation of memory (esp on the heap) that is (moderately) expensive.

You can just have local variables `C` and `D` and pass them into the functions that need them.  
This is clearer also, because now its transperent that those functions need those inputs (and not anything else you didn’t pass to it).  
So one can look at it and see what it used.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [January 27, 2020, 11:07pm UTC](https://discourse.julialang.org/t/question-about-functors/33876/4 "2020-01-27T23:07:47Z")

</div>

Eh, I didn’t notice that yet about Setfield.jl. Thanks for letting me know.

Regarding the other stuff, `C` and `D` are just stand ins. The actual number of things is nearing 20. It is stuff that I precompute so that the actual `updateA!`-type functions do a minimal amount of work. Perhaps I could separate that off (the stuff that is never updated once created) to be a different struct that gets passed around. I want to keep as much of it together as possible because it is not just used in the solution. Lots of it will continue to be in use afterwards in simulation and testing.

---

<div class="post-metadata">

**Author:** ![Nosferican](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nosferican/32/9275_2.png) [@Nosferican](https://discourse.julialang.org/u/Nosferican)\
**Post date:** [January 28, 2020, 5:25am UTC](https://discourse.julialang.org/t/question-about-functors/33876/5 "2020-01-28T05:25:53Z")

</div>

```julia
mutable struct EconomicProblem{A, B, C, D, ...}
  A
  B
  C
  D
  ...
end
function solve!(model::EconomicProblem)
  Δ = Inf
  while Δ > tolerance
    Δ₀ = updateA!(m)
    Δ₁ = updateB!(m)
    Δ = ...
  end
end

```

That’s a pretty natural structure and sound strategy. I would use a `mutable struct` for updating the values in-place. I would also make he `updateX!` methods return the components to determine convergence directly. For performance, either specify the types in the `struct` definition or if they might differ or use parametrization.

---

<div class="post-metadata">

**Author:** ![Tamas\_Papp](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tamas_papp/32/25949_2.png) [@Tamas\_Papp](https://discourse.julialang.org/u/Tamas_Papp)\
**Post date:** [January 28, 2020, 5:50am UTC](https://discourse.julialang.org/t/question-about-functors/33876/6 "2020-01-28T05:50:20Z")

</div>

> [@tbeason](#):
>
> Do I need to worry about unexpected behaviors here, which could be very very difficult to debug? I think of functors as operating on or within themselves (perhaps this is completely incorrect), so it feels weird to “pass” `m` to another mutating function as part of this process.

In principle, you can make this work, and it is the same `m` inside the mutating callable.

But in practice, I would suggest using a functional style:

1. group fixed parameters (eg `C`, `D`, …) into an (immutable) `struct`, which we call `params` below,

2. define `solve_for_A(params, B)` to get `A`, and similarly `solve_for_B(params, A)`,

3. write a function `solve_iteratively(params; A = initial_guess_A(params))` that performs the loop above.

Code like this is usually easier to reason about. You can later switch to re-using pre-allocated `A` and `B`, eg `solve_for_A!(A, params, B)`, but the performance gains are usually not worth the complexity.

---

<div class="post-metadata">

**Author:** ![oxinabox](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oxinabox/32/206603_2.png) [@oxinabox](https://discourse.julialang.org/u/oxinabox)\
**Post date:** [January 28, 2020, 10:08am UTC](https://discourse.julialang.org/t/question-about-functors/33876/7 "2020-01-28T10:08:38Z")

</div>

> [@tbeason](#):
>
> . The actual number of things is nearing 20. It is stuff that I precompute so that the actual `updateA!` -type functions do a minimal amount of work. Perhaps I could separate that off (the stuff that is never updated once created) to be a different struct that gets passed around. I want to keep as much of it together as possible because it is not just used in the solution. Lots of it will continue to be in use afterwards in simulation and testing.

Oh thats _really_ unfortunate.  
There are no good software engineering answers if you are in this space.  
Because of the whole [“humans can only keep about 7 things in working memory”](https://en.wikipedia.org/wiki/Working_memory#Capacity) thing.

The normal software engineering advice would be to rearrange your program such that each function only had at most 7 variables.  
Which one migh accomplish by drawing the boundries between functions differently.  
Or by grouping some into structs with 7 or fewer fields, where that struct could be thought of as a single entitiy.  
e.g. the train function takes a single argument `optimizer_settings` which it passes to the optimizer without looking inside (thus counting as 1). The optimizer takes that and does look inside counting as (say) 5 of its variables, with the `loss` and the `parameters` being tuned making uop to 7.

But I do appreciate this may not be a reasonable expectation for some scientific code.

Good luck.

---

<div class="post-metadata">

**Author:** ![tbeason](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/tbeason/32/15898_2.png) [@tbeason](https://discourse.julialang.org/u/tbeason)\
**Post date:** [January 28, 2020, 4:41pm UTC](https://discourse.julialang.org/t/question-about-functors/33876/8 "2020-01-28T16:41:44Z")

</div>

Great replies while I slept – I should sleep more often!

Thanks for the suggestions. I will update my design accordingly.
