# How to programmatically generate different functions?

**URL:** <https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152>\
**Category:** General Usage\
**Tags:** metaprogramming\
**Created:** [March 20, 2022, 5:14am UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152 "2022-03-20T05:14:17Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![DenisTitov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/denistitov/32/23385_2.png) [@DenisTitov](https://discourse.julialang.org/u/DenisTitov)\
**Post date:** [March 20, 2022, 5:14am UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/1 "2022-03-20T05:14:17Z")

</div>

Hi all,

I want to figure out how to generate different version of a function programmatically.  
I beleive metaprogramming is what I need but wanted to ask for advice before implementing it.  
Apologies if below is a bit confusing and happy to answer any clarifying questions.

Here’s what I want:  
I have different versions of a similar function that I fit to data.  
I have working code that does the fitting so I don’t need any advice about that.  
Each function uses several `inputs`, produces one `output` depending on several `parameters`.

A very simple example can be a function like this:

```julia
function test_fun(input1, input2, parameter1, parameter2)
    output = input1/parameter1 + input2/parameter2
    return output
end

```

The actual function has 5 inputs, 10-25 parameters and produces one output.  
I want to be able to generate different versions of this function that contain different number of parameters, make some parameter=1, others =Inf and others =0.  
Then I’ll use a loop to generate different version of a function and fit it to data to figure out what is the minimal number of parameters that I need to achieve good fit.

What would be the best approach to do this?

I could be overthinking this but I plan to make a macro that will take a list of symbols of parameters that are undefined (i.e., the parameters that will be modified by fitting algorythm), a list of parameters that =1, a list of parameters that =0 and a list of parameters that =Inf. Then this marco will create a version of the function having undefined parameters as positional arguments and defined parameters as kwargs. Then I’ll use a loop through different lists of parameters to do the function generation + fitting.

Does this sound sensible? If yes, how should I go about writing such a macro?

I have read [Julia Manual Metaprogramming](https://docs.julialang.org/en/v1/manual/metaprogramming/) and [Introducing Julia/Metaprogramming - Wikibooks, open books for an open world](https://en.wikibooks.org/wiki/Introducing_Julia/Metaprogramming) and I think I could implement this but want to make sure I’m on the right track as it looks like it’ll take a bunch of hours/maybe days for me to do this as I’m still getting a hang of the metaprograming syntax.

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [March 20, 2022, 6:51am UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/2 "2022-03-20T06:51:23Z")

</div>

This sounds too complicated.

One idea: make a struct containing all the parameters and make one function that accepts an instance of the struct. Then instantiate the struct many times with different parameter values and pass it into the function.

---

<div class="post-metadata">

**Author:** ![DNF](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dnf/32/10191_2.png) [@DNF](https://discourse.julialang.org/u/DNF)\
**Post date:** [March 20, 2022, 7:28am UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/3 "2022-03-20T07:28:17Z")

</div>

I don’t really understand what you want to do. But be aware that macros do not have access to any input or parameter values, or even type information. They do pure code transformations.

Perhaps you are looking for anonymous functions?

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [March 20, 2022, 8:46am UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/4 "2022-03-20T08:46:12Z")

</div>

Can you write a function that takes an array instead of the many parameter?  
Then using [Combinatorics.jl](https://github.com/JuliaMath/Combinatorics.jl) you can generate the different possible inputs.

Another way is to [splat](https://docs.julialang.org/en/v1/manual/faq/#The-two-uses-of-the-...-operator:-slurping-and-splatting) the array to a function which slurps the arguments. That way you could still call the function with individual parameters, but inside the function you could use it as an array again.

The parameters you don’t want to use you could set to missing, 2, nothing, NA, or something appropriate. Depends a bit on the type you want to use.

---

<div class="post-metadata">

**Author:** ![DenisTitov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/denistitov/32/23385_2.png) [@DenisTitov](https://discourse.julialang.org/u/DenisTitov)\
**Post date:** [March 20, 2022, 5:02pm UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/5 "2022-03-20T17:02:50Z")

</div>

Thanks for the suggestions @jar1, @DNF, @feanor12!

Sounds like my explanation of what I want is too confusing so let me try again.

I have a function:

```julia
function test_fun(input1, input2, parameter1; parameter2=Inf, parameter3=0)
    output = input1/parameter1 + input2/parameter2 + parameter3
    return output
end

```

I want to make a `for loop` that will automatically define different virsions of `test_fun` during each iterations like  
`test_fun(input1, input2, parameter1, parameter2, parameter3)` during 1st iteration, `test_fun(input1, input2, parameter1, parameter3; parameter2=Inf)` during 2nd iteration, `test_fun(input1, input2, parameter1, parameter2; parameter3=0)` during 3rd iteration,  
test\_fun(input1, input2, parameter1; parameter2=Inf, parameter3=0) during 4th iteration.

What would be a way to achieve this?

My rational is that the actual example has 5 inputs and 25 parameters so there are many combinations and I want to automate this procedure.

A more elaborate explanation of what I am doing is below if anyone is curious but I think it is not necessary to know the details below.

**Question:**  
I have data in this form: `input1`, `input2`, `input3`, `input4`, `input5` =\> `output`  
Specifically, the data describes activity of an enzyme (`output`) depending on concentrations of metabolites (`inputs`) but these details presumably don’t matter.  
I have several models that describe the activity of this enzyme which basically means I have functions that take `inputs` and convert it to `output` using a set of `parameters`, where `parameters` are various binding constants.  
The simplest model has 6 `parameters` and the most elaborate has 25 `parameters`.

**Current implementation:**  
I can estimate `parameters` by fitting to data.  
I have a function like below but with more inputs, more parameters and more complex math:

```julia
function test_fun(input1, input2, parameter1, parameter2, parameter3)
    output = input1/parameter1 + input2/parameter2 + parameter3
    return output
end

```

Each parameter has a specific role so they are not interchangeable.  
I calculate loss function of the form:

```julia
function test_loss(parameter1, parameter2, parameter3)
    loss = abs2(Data(input1, input2) - test_fun(input1, input2, parameter1, parameter2, parameter3)
    return loss
end

```

I then estimate parameters using BlackBoxOptim.jl that takes `test_loss(parameter1, parameter2, parameter3)` and calculates `parameter1, parameter2, parameter3` that minimize loss.

In order to remove various parameters from the model I set them to 1, 0 or Inf (there’s one specific default for each specific parameter) so an example of a reduced model without parameter2 will look like this:

```julia
function test_fun(input1, input2, parameter1, parameter3; parameter2=Inf)
    output = input1/parameter1 + input2/parameter2 + parameter3
    # input2/parameter2 term will become 0 as parameter2 in set to Inf
    return output
end

```

**What I want to change:**

Currently the model with 25 parameters is overfitting and the model with 6 parameters in underfitting and it seems that a model with about 12 parameters is enough to achieve best fit.

I want to write code that will loop through various versions of the model and calculate the fits for each version of the model so I can systematically find the model with least parameters that is sufficient to explain the data.

For example, the first iteration of the loop will use

```julia
test_fun(input1, input2, parameter1, parameter2, parameter3)

```

and calculate parameter1, parameter2, parameter 3 that yield best fit.

Another iteration will use

```julia
test_fun(input1, input2, parameter1, parameter3; parameter2=Inf)

```

and calculate parameter1, parameter 3 that yield best fit given that parameter2=Inf.

Another iteration will use

```julia
test_fun(input1, input2, parameter1, parameter2; parameter3=0)

```

and calculate parameter1, parameter2 that yield best fit given that parameter3=0.

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [March 20, 2022, 5:52pm UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/6 "2022-03-20T17:52:09Z")

</div>

So do you want a function `gen_f` to return a function that has a custom call pattern using the parameters that should be used in the optimization?

```julia
function testfun(in1,in2,p1,p2,p3)
   return something
end

gen_f(1) # return (in1,in2,p2,p3) -> testfun(in1,in2,Inf,p2,p3)
gen_f(2) # return (in1,in2,p1,p3) -> testfun(in1,in2,p1,Inf,p3)
gen_f(3) # return (in1,in2,p1,p2) -> testfun(in1,in2,p1,p2,Inf)

```

---

<div class="post-metadata">

**Author:** ![DenisTitov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/denistitov/32/23385_2.png) [@DenisTitov](https://discourse.julialang.org/u/DenisTitov)\
**Post date:** [March 20, 2022, 6:05pm UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/7 "2022-03-20T18:05:01Z")

</div>

Yes, that sounds right.

Perhaps the following is more exactly what I want:

```julia
function testfun(in1,in2,p1,p2,p3)
   return something
end

gen_f(1) # return (in1,in2,p2,p3) -> testfun(in1,in2,p2,p3; p1=Inf)
gen_f(2) # return (in1,in2,p1,p3) -> testfun(in1,in2,p1,p3; p2=Inf)
gen_f(3) # return (in1,in2,p1,p2) -> testfun(in1,in2,p1,p2; p3=Inf)
gen_f(4) # return (in1,in2,p1,p2,p3) -> testfun(in1,in2,p1,p2, p3)
gen_f(4) # return (in1,in2,p1) -> testfun(in1,in2,p1; p2=Inf, p3=Inf)
...

```

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [March 20, 2022, 6:52pm UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/8 "2022-03-20T18:52:14Z")

</div>

I think calling `f(a,b,c)` with `f(a,c;b=3)` does not work. How should the function know the order of the first two arguments?

```julia
julia> f(a,b,c) = (a,b,c)
f (generic function with 1 method)

julia> f(1,2,3)
(1, 2, 3)

julia> f(1,2;b=3)
ERROR: MethodError: no method matching f(::Int64, ::Int64; b=3)
Closest candidates are:
  f(::Any, ::Any, ::type) at REPL[50]:1 got unsupported keyword argument "b"
Stacktrace:
 [1] top-level scope

```

---

<div class="post-metadata">

**Author:** ![feanor12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/feanor12/32/8212_2.png) [@feanor12](https://discourse.julialang.org/u/feanor12)\
**Post date:** [March 20, 2022, 6:59pm UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/9 "2022-03-20T18:59:42Z")

</div>

This can for sure be written in a nicer way.

```julia
function testf(a,b,p1,p2,p3)
    @info "call with", (a,b,p1,p2,p3)
end

function genf(i)

    (a,b,p...) ->begin
        p_new = []
        param = collect(p)
        mask = Bool.(digits(i,base=2,pad=3))
        for i in mask
            if i
                push!(p_new,Inf)
            else
                push!(p_new,popfirst!(param))
            end
        end
        testf(a,b,p_new...)
    end

end

```

```julia
julia> for i in 0:7
           genf(i)(1,2,3,4,5)
       end
[ Info: ("call with", (1, 2, 3, 4, 5))
[ Info: ("call with", (1, 2, Inf, 3, 4))
[ Info: ("call with", (1, 2, 3, Inf, 4))
[ Info: ("call with", (1, 2, Inf, Inf, 3))
[ Info: ("call with", (1, 2, 3, 4, Inf))
[ Info: ("call with", (1, 2, Inf, 3, Inf))
[ Info: ("call with", (1, 2, 3, Inf, Inf))
[ Info: ("call with", (1, 2, Inf, Inf, Inf))

julia> genf(1)(1,2,3,4)
[ Info: ("call with", (1, 2, Inf, 3, 4))

julia> genf(3)(1,2,3)
[ Info: ("call with", (1, 2, Inf, Inf, 3))

```

---

<div class="post-metadata">

**Author:** ![DenisTitov](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/denistitov/32/23385_2.png) [@DenisTitov](https://discourse.julialang.org/u/DenisTitov)\
**Post date:** [March 21, 2022, 3:17am UTC](https://discourse.julialang.org/t/how-to-programmatically-generate-different-functions/78152/10 "2022-03-21T03:17:59Z")

</div>

Beautiful, thanks @feanor12! I think this solution should work for me! Thanks for your time and help!
