# Global variables and program structure

**URL:** https://discourse.julialang.org/t/global-variables-and-program-structure/6188
**Category:** General Usage
**Created:** [October 1, 2017, 7:43pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188 "2017-10-01T19:43:32Z")
**Posts on this page:** 16
**Page:** 1

<div class="post-metadata">

### Author: ![turtle](https://avatars.discourse-cdn.com/v4/letter/t/ecb155/32.png) [@turtle](https://discourse.julialang.org/u/turtle)
#### Post date: [October 1, 2017, 7:43pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/1 "2017-10-01T19:43:32Z")

</div>

I am not proud of my program structure.

My code is contained within a single module,  
my main variables are contained in 8 mutable composite types  
sometimes with as many as 30 type-annotated fields.  
Some of my functions create the main variables as const globals  
and these are conveniently used at various places in other functions.  
Exported variables and functions are used from the REPL.

I know that this is considered bad programming practice  
and type inference may fail at some places.  
So I have tried hard to pass these variables as arguments  
to all my functions but I have never succeded.  
With several call levels the code becomes too ugly  
and quick program development becomes a pain.

I really expect the arrival of type-annotated globals,  
and hope that any performance penalty will be gone.

But please advise:

- Is this program structure really that terrible?
- How do you arrange your code in a better way?

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [October 1, 2017, 8:14pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/2 "2017-10-01T20:14:50Z")

</div>

> [@turtle](#):
>
> Is this program structure really that terrible?

One of the main problems with that style is that your logic is non-local and hard to debug.

> [@turtle](#):
>
> How do you arrange your code in a better way?

Put your variables into structs, and pass those around (see [Parameters.jl](https://github.com/mauro3/Parameters.jl) for some helper macros). Break your functions up into smaller ones which only do one thing and thus only need access to a few variables. Compose those smaller functions into larger ones.

> [@turtle](#):
>
> quick program development becomes a pain.

There is definitely a trade-off between quick programming and writing maintainable code. But at least for bigger projects it does pay off as eventually there will be code maintenance and refactoring.

---

<div class="post-metadata">

### Author: ![turtle](https://avatars.discourse-cdn.com/v4/letter/t/ecb155/32.png) [@turtle](https://discourse.julialang.org/u/turtle)
#### Post date: [October 1, 2017, 8:42pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/3 "2017-10-01T20:42:45Z")

</div>

> [@mauro3](#):
>
> Put your variables into structs, and pass those around

My variables are already packed into structs.  
Passing them around is the problem.

When variables are packed logically into 8 different structs  
passing around various combinations of 8 different structs  
as function arguments can become really complex.

Consider the extreme case:  
One may pack ALL main variables (hundreds of them) into a SINGLE struct,  
then only a single extra argument must be passed at each function call.

But is this really a better programming style?

---

<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: [October 2, 2017, 6:53am UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/4 "2017-10-02T06:53:17Z")

</div>

It is much easier to talk about program structure with concrete code in mind. If you post a minimal working example, you may get more specific advice. Sometimes the effort to create a MWE itself is helpful in reorganizing your program.

---

<div class="post-metadata">

### Author: ![mauro3](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mauro3/32/292_2.png) [@mauro3](https://discourse.julialang.org/u/mauro3)
#### Post date: [October 2, 2017, 8:14am UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/5 "2017-10-02T08:14:52Z")

</div>

I think this is an unlikely venue to get you a satisfactory answer to such a broad and not really Julia specific question. I see two possibilities how this forum could help you along: recommended books and example codes. If you are into physical models then this relatively simple code which calculates steady state subglacial drainage may be of use: [Bitbucket](https://bitbucket.org/maurow/rchannelode.jl).

Maybe someone knows a good book? Or more/better example packages?

---

<div class="post-metadata">

### Author: ![turtle](https://avatars.discourse-cdn.com/v4/letter/t/ecb155/32.png) [@turtle](https://discourse.julialang.org/u/turtle)
#### Post date: [October 2, 2017, 10:00am UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/6 "2017-10-02T10:00:00Z")

</div>

Thank you for the code example.  
And yes, other examples are welcome.

---

<div class="post-metadata">

### Author: ![damonturney](https://avatars.discourse-cdn.com/v4/letter/d/ecae2f/32.png) [@damonturney](https://discourse.julialang.org/u/damonturney)
#### Post date: [May 7, 2019, 8:28pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/7 "2019-05-07T20:28:13Z")

</div>

turtle: What did you ultimately decide to do with your program structure? I have the exact same problem that you mentioned here, and am very interested in what you ultimately did.

mauro3: I disagree that this is not a “Julia specific” conversation. Passing parameters around, and dealing with the scope of parameter spaces, and dealing with modules vs classes (in other languages) vs methods (in other languages), and the structure of using/passing the parameters in functions, and organizing functions within classes or within modules or what not, is quintessentially specific to the language. A true “object oriented” language would execute these tasks differently than a “function-based” language, which in turn would be different than whatever Julia is emerging to become. As Julia emerges into the world, it’s important for people to discuss the best program structure and methods for passing parameters.

---

<div class="post-metadata">

### Author: ![turtle](https://avatars.discourse-cdn.com/v4/letter/t/ecb155/32.png) [@turtle](https://discourse.julialang.org/u/turtle)
#### Post date: [May 9, 2019, 10:45am UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/8 "2019-05-09T10:45:56Z")

</div>

I was unable to find a more convenient option.  
My program still defines some global structures within functions,  
just at `v0.7.0` I was forced to change `const global` to `global`.  
Of course I tried to minimize their occurrences and tested that the speed penalty is tolerable

So my use case is still this:  
All my functions live in a single module.  
I use the REPL for interactive calculations,  
and most calculations are based on functions of the module.  
A few functions of this module create some global structures,  
and these are accessible to all other functions of the module.

This program structure saves an awful lot of typing in the REPL,  
because some main variables are not part of all function argument lists.  
Also, as a single function call is shorter, a single command line  
can contain several function calls as a “mini project” – without any visual clutter.

---

<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: [May 9, 2019, 12:03pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/9 "2019-05-09T12:03:02Z")

</div>

> [@turtle](#):
>
> This program structure saves an awful lot of typing in the REPL,  
> because some main variables are not part of all function argument lists.

Again, hard to say without seeing some code, but it is almost certain that there is a better way to do it. Eg even just grouping _all_ those global variables in a `struct` and passing them around could be a huge improvement with little extra typing.

---

<div class="post-metadata">

### Author: ![turtle](https://avatars.discourse-cdn.com/v4/letter/t/ecb155/32.png) [@turtle](https://discourse.julialang.org/u/turtle)
#### Post date: [May 9, 2019, 12:35pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/10 "2019-05-09T12:35:21Z")

</div>

All my important variables are already grouped into 3 logically disjunct `global structs`.

Do you suggest to group all unrelated variables into a single global `struct`?  
(Long ago I tried it, but it did not feel logical.)

---

<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: [May 9, 2019, 12:42pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/11 "2019-05-09T12:42:23Z")

</div>

> [@turtle](#):
>
> Do you suggest to group all unrelated variables into a single global `struct` ?

You keep missing this, so for the third time: it is very difficult to suggest anything concrete without seeing the code, or an MWE.

---

<div class="post-metadata">

### Author: ![damonturney](https://avatars.discourse-cdn.com/v4/letter/d/ecae2f/32.png) [@damonturney](https://discourse.julialang.org/u/damonturney)
#### Post date: [May 9, 2019, 2:34pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/12 "2019-05-09T14:34:19Z")

</div>

I think I have the exact same problem as turtle, and here is my example solution: define structures (which behave exactly like const globals) and hope that I’m not taking a performance hit for doing so. See code below:

```julia
module workspace
    module stuff1
        struct teststruct
            x::Array{Float64,1} #this will be a 1000-element array that behaves like a const global array. I can mutate it's elements!
            y::Array{Float64,1} #this will be a 1-element array that behaves like a const global array. I can mutate it's elements!
            z::Float64 #this will be a value that I cannot mutate!
        end
        data=teststruct(rand(1000),[6.7],9.1);
        println(data.x[1:10])
    end
    module run_calculations1
        import ..stuff1.data
        #define further parameters here
        r=8.0
        function run_simulation(data,r)
            s = 0.0
            y=1.0
            for i in 1:length(data.x)
                for j in 1:length(data.x)
                    data.x[i] = rand(1)[1]*y*data.z+data.y[1]+r
                end
            end
            return data
        end
    end
    time() = @time y=run_calculations1.run_simulation(stuff1.data,run_calculations1.r)
    time()
    time()
    time()
    time()
end

```

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [May 9, 2019, 3:00pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/13 "2019-05-09T15:00:54Z")

</div>

> [@damonturney](#):
>
> define structures (which behave exactly like const globals) and hope that I’m not taking a performance hit for doing so.

That hope is unfortunately in vain. `data` and `r` are global variables and should be `const` if you want them to not slow down your code.

---

<div class="post-metadata">

### Author: ![damonturney](https://avatars.discourse-cdn.com/v4/letter/d/ecae2f/32.png) [@damonturney](https://discourse.julialang.org/u/damonturney)
#### Post date: [May 9, 2019, 5:32pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/14 "2019-05-09T17:32:09Z")

</div>

I believe the variable “r” is local scope inside the function because I passed it into the function as an argument to the function. As far as “data”, as far as I’ve seen and heard, Julia structures are automatically constant globals! Constant globals run just as fast as locals – as far as I’m aware.

I’ve done the benchmarking, and this assumption appears to be true, because the benchmark times for the following code shows great performance with my global structure “data” vs local variables.

Compare this code and benchmark:

```julia
module test
    module stuff1
        struct teststruct
            x::Array{Float64,1} #this will be a 1000-element array that behaves like a const global array. I can mutate it's elements!
            y::Array{Float64,1} #this will be a 1-element array that behaves like a const global array. I can mutate it's elements!
            z::Float64 #this will be a value that I cannot mutate!
        end
        data=teststruct(rand(1000),[6.7],9.1);
        println(data.x[1:10])
    end
    module run_calculations1
        import ..stuff1.data
        #define further parameters here
        r=8.0
        function run_simulation(data,r)
            s = 0.0
            y=1.0
            for i in 1:length(data.x)
                for j in 1:length(data.x)
                    data.x[i] = rand(1)[1]*y*data.z+data.y[1]+r
                end
            end
            return data
        end
    end
    time() = @time y=run_calculations1.run_simulation(stuff1.data,run_calculations1.r)
    time()
    time()
    time()
    time()
end
OUTPUTS:
[0.323492, 0.235494, 0.51633, 0.784921, 0.66276, 0.312472, 0.72803, 0.40744, 0.974881, 0.852874]
  0.139204 seconds (1.04 M allocations: 93.487 MiB, 22.53% gc time)
  0.101172 seconds (1000.00 k allocations: 91.553 MiB, 31.57% gc time)
  0.097960 seconds (1000.00 k allocations: 91.553 MiB, 31.24% gc time)
  0.085701 seconds (1000.00 k allocations: 91.553 MiB, 27.62% gc time)

```

with this one:

```julia
module test
   module stuff1
       struct teststruct
           x::Array{Float64,1} #this will be a 1000-element array that behaves like a const global array. I can mutate it's elements!
           y::Array{Float64,1} #this will be a 1-element array that behaves like a const global array. I can mutate it's elements!
           z::Float64 #this will be a value that I cannot mutate!
       end
       data=teststruct(rand(1000),[6.7],9.1);
       println(data.x[1:10])
   end
   module run_calculations1
       import ..stuff1.data
       #define further parameters here
       function run_simulation()
           s = 0.0
           y=1.0
           x=[1.0]
           for i in 1:1000
               for j in 1:1000
                   x[1] = rand(1)[1]*y*9.1+6.7+8.0
               end
           end
           return x
       end
   end
   time() = @time y=run_calculations1.run_simulation()
   time()
   time()
   time()
   time()
end
OUTPUTS:
[0.598739, 0.238504, 0.570769, 0.768084, 0.30716, 0.0337915, 0.361736, 0.715133, 0.96916, 0.987557]
  0.100308 seconds (1.00 M allocations: 91.553 MiB, 26.71% gc time)
  0.091171 seconds (1.00 M allocations: 91.553 MiB, 21.15% gc time)
  0.077898 seconds (1.00 M allocations: 91.553 MiB, 22.52% gc time)
  0.084541 seconds (1.00 M allocations: 91.553 MiB, 22.64% gc time)

```

@kristoffer.carlsson I’d be excited to learn some way to improve this example code’s performance. It’s the best I got now.

---

<div class="post-metadata">

### Author: ![kristoffer.carlsson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/kristoffer.carlsson/32/22_2.png) [@kristoffer.carlsson](https://discourse.julialang.org/u/kristoffer.carlsson)
#### Post date: [May 9, 2019, 5:37pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/15 "2019-05-09T17:37:19Z")

</div>

I missed that you passed them into the function. If that’s the case, it is fine (this technique is called a function barrier).

---

<div class="post-metadata">

### Author: ![ExpandingMan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/expandingman/32/866_2.png) [@ExpandingMan](https://discourse.julialang.org/u/ExpandingMan)
#### Post date: [May 9, 2019, 5:53pm UTC](https://discourse.julialang.org/t/global-variables-and-program-structure/6188/16 "2019-05-09T17:53:09Z")

</div>

Not sure how helpful this comment is, but I have taken to always including global variables as default keyworld arguments. For example

```julia
const GLOBAL_VALUE = 1

function somefunction(a, b; global_value=GLOBAL_VALUE)
    # do stuff
end

```

Of course, this only works for global variables which are basically immutable (I say “basically”, because you could, for example, initialize some global container during ` __init__ ()`). An even better practice is to set the default to the call of another function that reads in a config file (I like TOML), but this is only really appropriate with memoization.

Another thing that I tend to do to eliminate global values is to stick things which originally I had envisioned as global into my `struct`s. About 90% of the time this is the better coding choice anyway (i.e. because the value wasn’t _really_ global).

The vast majority of the time, I find that global variables really are unnecessary, and I was better off without them in the first place. The one thing I have yet to really feel like I’ve cracked is memoization. I really want a nice drop-in memoization scheme that I feel comfortable with, and haven’t figured out anything I’m totally satisfied with yet. I think for me the ultimate solution is to have a `@moizable` macro or something like that that one calls when declaring `struct`s which makes that struct appropriate for memoizing values into. The details, however, are messy.
