# Concrete Example 0805: how to prevent using global variable in the module?

**URL:** <https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917>\
**Category:** General Usage\
**Created:** [August 6, 2021, 1:01am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917 "2021-08-06T01:01:45Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![CRquantum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/crquantum/32/27824_2.png) [@CRquantum](https://discourse.julialang.org/u/CRquantum)\
**Post date:** [August 6, 2021, 1:01am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917/1 "2021-08-06T01:01:45Z")

</div>

I learned from all of you that Julia discourage global variable. Thank you very much indeed!

I am translating my Fortran code to Julia. It is a Monte Carlo parametric expectation maximization code. Basically using gaussian mixture model.

Here I show a module call Mixture, as a small example. My purpose is simple.

I define a type Mean\_covar, then I need an array called musigma. Each element of the musigma array is of the type Mean\_covar.

The size of array musigma, and the value of its each element will be initialized by calling the function mean\_covar\_init in the main program which will use this ‘Mixture’ module.

I also wish to export this array musigma, so that I can directly use it without do Mixture.musigma all the time.

Here is the module:

```
module Mixture

export musigma

mutable struct Mean_covar
    mu::Array{Float64,2}
    sigma::Array{Float64,2}
    w::Float64
end

global const musigma = Array{Mean_covar,1}()  

function mean_covar_init(kmix::Int64,dim_p::Int64
                        ,weight::Array{Float64,1}
                        ,sigma::Array{Float64,3}
                        ,mu::Array{Float64,2})
    @assert length(weight) == kmix
    @assert size(sigma) == (kmix,dim_p,dim_p)
    @assert size(mu) == (kmix,dim_p)
    resize!(musigma, kmix) 
    for k in 1:kmix
        musigma[k] = Mean_covar(zeros(dim_p,1),zeros(dim_p,dim_p),0.0)
        musigma[k].mu[1,1] = mu[k,1]
        musigma[k].mu[2,1] = mu[k,2]
        musigma[k].sigma[1,1] = sigma[k,1,1]
        musigma[k].sigma[2,2] = sigma[k,2,2]
        musigma[k].w = weight[k]
    end
    return nothing
end

end

```

Note that I added const for musigma array just to lock the type of the musigma array.

Now my question is, in order to export musigma array, do I have to declare it as a global array?

---

<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:** [August 6, 2021, 1:21am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917/2 "2021-08-06T01:21:15Z")

</div>

It will be much better if you initialize mussigma inside the init function and return it to the user.  
Then pass mussigma to the next function that will use it as a parameter.

Something like:

```julia
module Mixture

  export init, compute

  function init(...)
     mussigma = Vector{...}(undef,...)
     ...
     return mussigma
  end

  function compute(mussigma)
    ...
    return result
  end

end

using Mixture

mussigma = init(...)

result = compute(mussigma)

```

Try to forget completely about the possibility of using global variables, that is the best advice.

---

<div class="post-metadata">

**Author:** ![genkuroki](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/genkuroki/32/18030_2.png) [@genkuroki](https://discourse.julialang.org/u/genkuroki)\
**Post date:** [August 6, 2021, 2:15am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917/3 "2021-08-06T02:15:03Z")

</div>

I agree with leandromartinez98-san.

As [I already mentioned](https://discourse.julialang.org/t/how-to-correctly-define-and-use-global-variables-in-the-module-in-julia/65720/18), in my personal opinion, it is safer to avoid using constants to fix the types, especially when using Julia for scientific purposes.

For example, if you fix the type to Float64, you will not be able to use automatic differentiation. (cf. [Avoid writing overly-specific types](https://docs.julialang.org/en/v1/manual/style-guide/#Avoid-writing-overly-specific-types))

See also

> [@How to prevent using global arrays in iteration in the module](https://discourse.julialang.org/t/how-to-prevent-using-global-arrays-in-iteration-in-the-module/65857/12):
>
> No. The function LifeGame.gif!(board, niters; ...) in my example contains the for loop updating niters times the global variables initialized by boardrandom = LifeGame.randboard() and board5x5 = LifeGame.fivexfive() outside the module LifeGame and plotting each step to gif animations. In the module LifeGame: Outside the module LifeGame: LifeGame.update!(board, niters) is not used in the example, but can update a LifeGame.Board type variable without plotting. In the module LifeGame: Th…

In this case, there is no need to share something global with multiple functions without going through function arguments.

I have tried minimal changes.

**Code**

```julia
module O

export musigma

struct Mean_covar{T}
    mu::Vector{T}
    sigma::Matrix{T}
    w::Array{T,0}
end

function mean_covar_init(kmix, dim_p, 
        weight::AbstractVector{T},
        sigma::AbstractArray{T,3},
        mu::AbstractMatrix{T}) where T
    @assert size(weight) == (kmix,)
    @assert size(sigma) == (kmix, dim_p, dim_p)
    @assert size(mu) == (kmix, dim_p)
    musigma = Vector{Mean_covar{T}}(undef, kmix)
    for k in 1:kmix
        musigma[k] = Mean_covar(zeros(T, dim_p), zeros(T, dim_p, dim_p), fill(zero(T)))
        musigma[k].mu[1,1] = mu[k,1]
        musigma[k].mu[2,1] = mu[k,2]
        musigma[k].sigma[1,1] = sigma[k,1,1]
        musigma[k].sigma[2,2] = sigma[k,2,2]
        musigma[k].w[] = weight[k]
    end
    musigma
end

end

```

```julia
kmix = 5
dim_p = 3
weight = rand(kmix)
sigma = rand(kmix, dim_p, dim_p)
mu = rand(kmix, dim_p)

musigma64 = O.mean_covar_init(kmix, dim_p, weight, sigma, mu)
@show typeof(musigma64) size(musigma64)
@show musigma64[1].mu musigma64[1].sigma musigma64[1].w;

```

**Result**

````julia
typeof(musigma64) = Vector{Main.O.Mean_covar{Float64}}
size(musigma64) = (5,)
(musigma64[1]).mu = [0.25133930343144617, 0.6524185771129412, 0.0]
(musigma64[1]).sigma = [0.6391609541493193 0.0 0.0; 0.0 0.8803430485817509 0.0; 0.0 0.0 0.0]
(musigma64[1]).w = fill(0.6189491252747268)```

````

**You can also use Float32 type.**

```julia
weight32 = rand(Float32, kmix)
sigma32 = rand(Float32, kmix, dim_p, dim_p)
mu32 = rand(Float32, kmix, dim_p)

musigma32 = O.mean_covar_init(kmix, dim_p, weight32, sigma32, mu32)
@show typeof(musigma32) size(musigma32)
@show musigma32[1].mu musigma32[1].sigma musigma32[1].w;

```

```julia
typeof(musigma32) = Vector{Main.O.Mean_covar{Float32}}
size(musigma32) = (5,)
(musigma32[1]).mu = Float32[0.27483153, 0.21964681, 0.0]
(musigma32[1]).sigma = Float32[0.16200805 0.0 0.0; 0.0 0.9208745 0.0; 0.0 0.0 0.0]
(musigma32[1]).w = fill(0.2774073f0)

```

If there is a possibility of using GPU, it is important to be able to use Float32 as well. However, in the above example, the type of the fields of `Mean_covar` type are fixed to `Array`’s, the design of which is insufficient to use GPU.

**Changes**

- `mutable struct Mean_covar` → immutable `struct Mean_covar{T}` (fields are all mutable)
- type of `mu` → `Vector{T}` = `Array{T,1}`
- type of `weight` → `Matrix{T}` = `Array{T,2}`
- type of `w` → `Array{T,0}`, 0-dimensional array (this is mutable)
- delete `global const musigma` in the module
- `mean_covar_init` constructs and returns `musigma`

Point: The module `O` above does not contain any concrete type names like `Float64`.

“[In general, you should use the most general applicable abstract types for arguments, and when in doubt, omit the argument types.](https://github.com/JuliaLang/julia/blob/master/doc/src/manual/functions.md#argument-type-declarations)”

---

<div class="post-metadata">

**Author:** ![CRquantum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/crquantum/32/27824_2.png) [@CRquantum](https://discourse.julialang.org/u/CRquantum)\
**Post date:** [August 6, 2021, 3:39am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917/4 "2021-08-06T03:39:45Z")

</div>

> [@genkuroki](#):
>
> “[In general, you should use the most general applicable abstract types for arguments, and when in doubt, omit the argument types.](https://github.com/JuliaLang/julia/blob/master/doc/src/manual/functions.md#argument-type-declarations)”

Thank you very much.  
Right, I agree, that is what I did in Fortran, whenever possible use generic functions or types.

It is just that I heard the code will be slow if Julia are always trying to do type conversion or something. So if I define just Float, instead of Float64, will Julia smart enough to detect it is Float64 or Float32?  
I mean if some expressions are mixed of Float64 and Float32, will it be slower than simply defining everything with just Float64?

---

<div class="post-metadata">

**Author:** ![CRquantum](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/crquantum/32/27824_2.png) [@CRquantum](https://discourse.julialang.org/u/CRquantum)\
**Post date:** [August 6, 2021, 3:42am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917/5 "2021-08-06T03:42:21Z")

</div>

> [@genkuroki](#):
>
> ```julia
> struct Mean_covar{T}
> mu::Vector{T}
> sigma::Matrix{T}
> w::Array{T,0}
> end
> 
> ```

Thank you very much.  
May I ask, what does the T mean?

---

<div class="post-metadata">

**Author:** ![jzr](https://avatars.discourse-cdn.com/v4/letter/j/eb9ed0/32.png) [@jzr](https://discourse.julialang.org/u/jzr)\
**Post date:** [August 6, 2021, 3:45am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917/6 "2021-08-06T03:45:57Z")

</div>

> Type parameters are introduced immediately after the type name, surrounded by curly braces

[https://docs.julialang.org/en/v1/manual/types/#Parametric-Types](https://docs.julialang.org/en/v1/manual/types/#Parametric-Types)

---

<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:** [August 6, 2021, 10:50am UTC](https://discourse.julialang.org/t/concrete-example-0805-how-to-prevent-using-global-variable-in-the-module/65917/7 "2021-08-06T10:50:08Z")

</div>

> [@CRquantum](#):
>
> It is just that I heard the code will be slow if Julia are always trying to do type conversion or something.

About that you will find many many posts, because it is the core of how Julia works. But my note on that is this one: [Type instability · JuliaNotes.jl](https://m3g.github.io/JuliaNotes.jl/stable/instability/)
