# Suggestion for how to organize code that requires many parameters

**URL:** https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230
**Category:** General Usage
**Created:** [January 26, 2025, 2:50pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230 "2025-01-26T14:50:17Z")
**Posts on this page:** 13
**Page:** 1

<div class="post-metadata">

### Author: ![sylvaticus](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sylvaticus/32/203883_2.png) [@sylvaticus](https://discourse.julialang.org/u/sylvaticus)
#### Post date: [January 26, 2025, 2:50pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/1 "2025-01-26T14:50:18Z")

</div>

I have a “model” that require many parameters and I am struggling to keep a reference to all the paramters in the various subcalls. I would like instead to define a julia file to host the “default” parameters, itself a parameter with the default default parameters 😉  
I would like to keep the parameter file(s) as a julia file (instead of, let’s say, a json or toml file) because in these files I would like to make simple computations, typically simple calibrations of my model parameters from some more “raw” data.

So I have a function `mymodel` that I would like to call with:

`mymodel(defaults="somefile.jl", par2=1.0, par4=10)` where `par2` and `par4` override those defined in `somefile.jl`

`mymodel` would then be defined with:  
`function mymodel(;defaults="default_of_defaults.jl",kwargs...)`

Does it look reasonable ?  
Can I just `include(defaults)` in the body of my function and then build a struct with the parameters to pass it around ?  
However, this means I would have multiple `include` as I call the function multiple times…

---

<div class="post-metadata">

### Author: ![lmiq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/lmiq/32/18314_2.png) [@lmiq](https://discourse.julialang.org/u/lmiq)
#### Post date: [January 26, 2025, 2:54pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/2 "2025-01-26T14:54:16Z")

</div>

I would use a struct, as suggested here: [How to allow users to safely change package "constants"? - #6 by lmiq](https://discourse.julialang.org/t/how-to-allow-users-to-safely-change-package-constants/115173/6)

There are other options in that thread. There is also a Preferences.jl package, which might be what you need.

---

<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: [January 26, 2025, 3:01pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/3 "2025-01-26T15:01:19Z")

</div>

> [@sylvaticus](#):
>
> Can I just `include(defaults)` in the body of my function

The `include` function calls the compiler, so you probably don’t want to call it at run time.

---

<div class="post-metadata">

### Author: ![SteffenPL](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/steffenpl/32/206270_2.png) [@SteffenPL](https://discourse.julialang.org/u/SteffenPL)
#### Post date: [January 26, 2025, 3:47pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/4 "2025-01-26T15:47:15Z")

</div>

Maybe my approach is too simplistic, but I prefer to use simply named tuples and a preprocess function. That seems cleaner than an abstract framework around everything.

For example:

- toml file defines raw parameters, load as named tuple
- preprocess function gets raw parameters, inserts default values of from the toml input missing params and then does preprocessing.
- final parameter object is again a named type, e.g. no need to redefine structs etc.

A simplistic example looks like this:

```julia
function preprocess(p_raw)
    p_def = (x = 10,) 
    p = (p_def..., p_raw...)
    
    y = p.x^2

    p = (p..., y) 

    return p
end

```

There is a bit lot of unpacking and merges of names tuples, but that way it remains vanilla Julia code.

---

<div class="post-metadata">

### Author: ![rafael.guerra](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rafael.guerra/32/216610_2.png) [@rafael.guerra](https://discourse.julialang.org/u/rafael.guerra)
#### Post date: [January 26, 2025, 7:16pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/5 "2025-01-26T19:16:56Z")

</div>

@SteffenPL, semicolons missing? Like in:  
nt = (;(;nt1…, nt2…)…)

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [January 26, 2025, 7:33pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/6 "2025-01-26T19:33:58Z")

</div>

If you like defining your parameters with julia code but otherwise keep a file that mostly consists of top-level `x = ...` expressions, you could also try a macro that reads in the expressions from your settings file and collects all the top-level assigned variables into a NamedTuple or so. The settings file is read in at compile time so there’s no `eval` or `include` overhead.

If you have a file `settings.jl`:

```julia
a = 1 + 2
b = 3
c = strip(" hello $b ")
d = let 
    x = 1
    y = 2
    x + y
end

```

Then you could use the macro workflow like this, for example:

```julia
function globals_to_namedtuple(expr)
    syms = Symbol[]
    for arg in expr.args
        if arg isa Expr && arg.head == :(=)
            push!(syms, arg.args[1])
        end
    end
    quote
        let 
            $(expr)
            (; $(syms...),)
        end
    end
end

macro settings(path::String)
    globals_to_namedtuple(Meta.parseall(read(path, String)))
end

@settings "settings.jl"

# (a = 3, b = 3, c = "hello 3", d = 3)

```

---

<div class="post-metadata">

### Author: ![nhz2](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/nhz2/32/44428_2.png) [@nhz2](https://discourse.julialang.org/u/nhz2)
#### Post date: [January 26, 2025, 7:55pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/7 "2025-01-26T19:55:21Z")

</div>

I used to do something like this but found that using named tuples in the preprocessing function leads to huge compile times as the number of parameters grows, especially when doing many merges. Now I do the preprocessing using ordered dictionaries `Symbol=>Any` and convert to a name tuple at the end.

---

<div class="post-metadata">

### Author: ![matnbo](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/matnbo/32/220166_2.png) [@matnbo](https://discourse.julialang.org/u/matnbo)
#### Post date: [January 26, 2025, 7:57pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/8 "2025-01-26T19:57:48Z")

</div>

I don’t know if this could help but, in my modeling API, I chose to define a parameter container (mutable structure with the default parameter values) for each category of model function. And I built a function ([recovkw.jl](https://github.com/mlesnoff/Jchemo.jl/blob/ca2a4fa53fa34e237e0a5295a36a98d1a16efb99/src/utility.jl#L1097)) that loads the container (as well eventually replaces default values by those set in kwargs) when the function is called. A simple example is given below

```julia
## PLSR model function

Base.@kwdef mutable struct ParPlsr  
    nlv::Union{Int, Vector{Int}, UnitRange} = 1                    
    scal::Bool = false 
end 

function plskern!(X::Matrix, Y::Union{Matrix, BitMatrix}, weights::Weight; kwargs...)
    ## load defaults parameters values and eventually replaces some of 
    ## them by those set in kwargs by the user
    par = recovkw(ParPlsr, kwargs).par   
    ## End
    ...
end

```

and

```julia
model = plskern!(nlv = 15) # parameters inside the model will be nlv = 15, scal = false

```

---

<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: [January 26, 2025, 8:05pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/9 "2025-01-26T20:05:40Z")

</div>

> [@jules](#):
>
> could also try a macro that reads in the expressions from your settings file and collects all the top-level assigned variables into a NamedTuple

It would be simpler to just put a `NamedTuple` literal into a file and `include` it.

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [January 26, 2025, 8:21pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/10 "2025-01-26T20:21:08Z")

</div>

Sure but that doesn’t approximate the “yaml file with julia code” style as well

---

<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: [January 26, 2025, 8:25pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/11 "2025-01-26T20:25:53Z")

</div>

it’s just a few more commas 🤷‍♂️

---

<div class="post-metadata">

### Author: ![jules](https://avatars.discourse-cdn.com/v4/letter/j/41988e/32.png) [@jules](https://discourse.julialang.org/u/jules)
#### Post date: [January 26, 2025, 8:27pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/12 "2025-01-26T20:27:36Z")

</div>

If you don’t mix anything in between, like helper functions etc. That you can’t do with a single named tuple

---

<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: [January 26, 2025, 9:19pm UTC](https://discourse.julialang.org/t/suggestion-for-how-to-organize-code-that-requires-many-parameters/125230/13 "2025-01-26T21:19:29Z")

</div>

> [@jules](#):
>
> That you can’t do with a single named tuple

```julia
let
    # put whatever temporaries here
    (;
        # put named tuple elements here
    )
end

```
