# How to best carry around "state" in my program?

**URL:** https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335
**Category:** General Usage
**Created:** [August 29, 2023, 2:37pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335 "2023-08-29T14:37:41Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [August 29, 2023, 2:37pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/1 "2023-08-29T14:37:41Z")

</div>

I have to parse a configuration file and run a simulation based on the settings in that file. In some language like Python, I’d probably make a class, say _ConfigParser_ and it would both parse and store my configuration. Since I can’t rest on all of my old bad habits, I figured I’d ask for advice on new ways to do old things.

I guess I’m looking for a Julian way of doing things, not just something that doesn’t provoke the compiler to throw things.

### I could use global variables

Global variables have obvious problems (not to mention it winds up being `Dict{Any, Any}`.

```julia-auto
state::Dict = Dict()

function parsefile(fname)
    fh = open(fname)
    # ... read file, stuff info in state
end

function run_simulation()
    # ... run simulation based on state
end

parse_file("config.cfg")
run_simulation()

```

### I could use inner functions (closures?)

Also has problems, and my co-workers aren’t fond of.

```julia-auto
function simulate(fname)
    function parsefile(fh)
        # ... read file, stuff into `state`
    end

    state = Dict()
    fh = open(fname)
    parsefile(fh)

    run_simulation() # run simulation based on `state`
end

simulate("config.cfg")

```

### Chain things together somehow?

```julia-auto
function read_configuration(fname)
    dict = Dict()

    # ... read config, store in dict
    dict
end

function run_simulation(c)
    # based on configuration, run stuff
end

read_configuration("config.cfg") |> run_simulation

```

---

<div class="post-metadata">

### Author: ![adienes](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/adienes/32/37459_2.png) [@adienes](https://discourse.julialang.org/u/adienes)
#### Post date: [August 29, 2023, 3:02pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/2 "2023-08-29T15:02:55Z")

</div>

won’t be around until `1.11`, but this looks apropos [Scoped values by vchuravy · Pull Request #50958 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/pull/50958)

---

<div class="post-metadata">

### Author: ![stillyslalom](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stillyslalom/32/45687_2.png) [@stillyslalom](https://discourse.julialang.org/u/stillyslalom)
#### Post date: [August 29, 2023, 3:05pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/3 "2023-08-29T15:05:15Z")

</div>

All the Julia solvers I’m aware of (NLOpt, Optim, DiffEq, Trixi, …) use something like the third approach, where `read_configuration` returns a struct (if possible) rather than a dict, allowing more optimizations to be applied. This is related to the [function barrier](https://docs.julialang.org/en/v1/manual/performance-tips/#kernel-functions) performance tip. If there are a number of fundamentally-different configurations that could be simulated (say, 3D Cartesian _vs._ 2D r-z axisymmetric, or with _vs._ without body forces), those differences can be encoded in the type domain, and you’d then define multiple `simulate` methods, _e.g._ `simulate(initial_condition::Cartesian)` and `simulate(initial_condition::Axisymmetric)`.

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [August 29, 2023, 3:36pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/4 "2023-08-29T15:36:22Z")

</div>

Well, I always use a mutable struct for my configuration, which I store in a global const variable.

You can actually modify const mutable structs, so if I want to run the simulation based on a configuration file, but vary one parameter I can easily do that…

I pass this variable, named se (like settings) as first parameter to my functions. Sometimes I create  
a deep copy of the global settings, modify the copy and then call one of my functions.

I store the configuration on disc using a .yaml file which is easy to read and write for humans.

---

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [August 29, 2023, 4:01pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/5 "2023-08-29T16:01:11Z")

</div>

I’m glad to hear that at least someone else uses global const values … I know that they can cause performance issues if they are `Any` typed. Sometimes I feel like I am overcorrecting in favor of having few arguments - since there was a codebase I had to work on for a long time that had `fuction(way, way, way, too, many, darn, positional, arguments, good, greif)` … and no, that is not an exaggeration, one function (in Matlab) had 11 positional arguments. ☹

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [August 29, 2023, 4:01pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/6 "2023-08-29T16:01:12Z")

</div>

Imho, the third approach should always be supported. It just gives more flexibility, i.e., when running simulations across multiple different configurations etc.

In case, a good default is available it can be combined with global state:

1. Having a non-exported global with getter (and possibly setter) functions and default methods. E.g., `rand`uses this approach:

2. Again using some non-exported global state and providing a convenient way to execute code with different values:

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [August 29, 2023, 4:21pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/7 "2023-08-29T16:21:56Z")

</div>

> [@frylock](#):
>
> I know that they can cause performance issues if they are `Any` typed.

This is not true. They CANNOT be any typed if they are defined as const. They get  
a concrete type on first assignment, and you cannot change the type afterwords.  
Only disadvantage: You need to restart Julia if you extend your configuration struct  
and add new parameters.

---

<div class="post-metadata">

### Author: ![ufechner7](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/ufechner7/32/51363_2.png) [@ufechner7](https://discourse.julialang.org/u/ufechner7)
#### Post date: [August 29, 2023, 4:35pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/8 "2023-08-29T16:35:31Z")

</div>

> [@bertschi](#):
>
> Note that this pattern is very similar to _scoped values_ and similarly implemented by `task_local_storage`.

Too complicated for a simple scientist. And not needed unless your work in a team on a large piece of software.

---

<div class="post-metadata">

### Author: ![frylock](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/frylock/32/50213_2.png) [@frylock](https://discourse.julialang.org/u/frylock)
#### Post date: [August 29, 2023, 4:39pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/9 "2023-08-29T16:39:21Z")

</div>

I could be wrong about the intent of scoped values in Julia, but they seem like they were meant to be like [parameters in Lisp/Scheme](https://docs.racket-lang.org/reference/parameters.html)? They can in some cases make code cleaner, safer.

---

<div class="post-metadata">

### Author: ![bertschi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/bertschi/32/33462_2.png) [@bertschi](https://discourse.julialang.org/u/bertschi)
#### Post date: [August 29, 2023, 5:14pm UTC](https://discourse.julialang.org/t/how-to-best-carry-around-state-in-my-program/103335/10 "2023-08-29T17:14:58Z")

</div>

Yes, these are basically known as _dynamic variables_ in Common and Emacs Lisp. Especially, in Emacs they are put to [good use](https://www.gnu.org/software/emacs/emacs-paper.html#SEC17) enabling a highly extensible/configurable system.  
The main discussion nowadays seems to be how they should best interact with Threads or Tasks.
