# Implementing singletons for configuration variables

**URL:** <https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177>\
**Category:** General Usage\
**Tags:** question\
**Created:** [June 1, 2021, 8:41am UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177 "2021-06-01T08:41:39Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![sapo](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@sapo](https://discourse.julialang.org/u/sapo)\
**Post date:** [June 1, 2021, 8:41am UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/1 "2021-06-01T08:41:40Z")

</div>

Hello,  
I am used to having an object containing configuration variables for my project.

For instance, in Java, I use static [singletons](https://www.geeksforgeeks.org/singleton-class-java/) to ensure those configuration variables are instantiated only once for the whole life-cycle of the program and that they are available anywhere in the code.

In Python, this is the same as having a module – i.e. a file – containing variables, since the module loading system ensures that each module is 1) a global object instance 2) not instantiable 3) imported only once 4) accessible from anywhere

In Julia, I see two options.

1. use the `PatModule` package to mimic the Python behavior
2. use a constant instance of a struct that makes itself not instantiable anymore:

```julia
module Settings
    mutable struct SettingsStruct
        a::Int64
        b::Int64
        function SettingsStruct(a, b)
            eval(:(SettingsStruct(a, b) = error(
                "Cannot instantiate SettingsStruct twice")))
            return new(a, b)
        end
    end

    const s = Settings(2, 3)
end

```

Such a method allows having a constant global variable named `s` which contains my settings. Anywhere in the code, I am sure that `s` was not replaced by anyone, neither in interactive sessions.

I would just like to receive opinions about these two alternatives and other  
possible solutions.

---

<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:** [June 1, 2021, 8:57am UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/2 "2021-06-01T08:57:39Z")

</div>

There is also the option of creating the configuration object in your `main` function and passing it around through your functions.

And another, making a function that returns the configuration object.

I don’t really see the point of disabling multiple instantiation. What problem is prevented by that?

---

<div class="post-metadata">

**Author:** ![sapo](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@sapo](https://discourse.julialang.org/u/sapo)\
**Post date:** [June 1, 2021, 9:31am UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/3 "2021-06-01T09:31:36Z")

</div>

It’s one of the design patterns in the Gang of Four.

It’s useful if you have some resource that must not be instantiated twice by the user, for instance, consider the following function:

```julia
module Settings
    struct SettingsStruct
        a::Int64
        b::Int64
        function SettingsStruct(a)
            eval(:(SettingsStruct(a) = error(
                "Cannot instantiate SettingsStruct twice")))
            return new(a, a^2)
        end
    end

    const settingsStruct = SettingsStruct(4)
    const settingsDict = Dict(a => 4, b => 5)
end # module

module Library
    using Settings

    function test1(a::Int64, conf::SettingsStruct)
        print("I'm doing stuffs with $a and $(conf.b)")
    end

    function test2(a::Int64, conf::Dict)
        print("I'm doing stuffs with $a and $(conf["b"])")
    end
end # module

```

Then the code of the user

```julia
module UserCode
    using Library
    using Settings

    d = Dict("g" => 5)
    test1(3, Settings.settingsStruct)
    test2(3, d)

end # module

```

As you see, `test2` will fail, because the user has instantiated a wrong `d`.

If `SettingsStruct` could be instantiated twice, the user could pass new  
wrong values.

---

<div class="post-metadata">

**Author:** ![sijo](https://avatars.discourse-cdn.com/v4/letter/s/da6949/32.png) [@sijo](https://discourse.julialang.org/u/sijo)\
**Post date:** [June 1, 2021, 10:29am UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/4 "2021-06-01T10:29:04Z")

</div>

Your solution looks reasonable to me, except that redefining the constructor is very hackish (and do you need the struct the be mutable?).

You can instead check if the variable `s` is defined:

```julia
module Settings
    struct SettingsStruct
        a::Int64
        b::Int64
        function SettingsStruct(a, b)
            isdefined(Settings, :s) && error("Cannot instantiate SettingsStruct twice")
            return new(a, b)
        end
    end

    const s = SettingsStruct(2, 3)
end

```

See also [Implementing Singleton design pattern](https://discourse.julialang.org/t/implementing-singleton-design-pattern/61704).

However in this case I would just use a `const` with no additional check: you already get a warning if you change it:

> WARNING: redefinition of constant s. This may fail, cause incorrect answers, or produce other errors.

But yeah, I do wish it would give an error instead. The current behavior seems designed for playing around and prototyping rather than building robust applications.

This was recently discussed on [Behavior of reassignment to a `const` · Issue #38584 · JuliaLang/julia · GitHub](https://github.com/JuliaLang/julia/issues/38584).

---

<div class="post-metadata">

**Author:** ![Sukera](https://avatars.discourse-cdn.com/v4/letter/s/ce7236/32.png) [@Sukera](https://discourse.julialang.org/u/Sukera)\
**Post date:** [June 1, 2021, 11:13am UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/5 "2021-06-01T11:13:47Z")

</div>

> [@sapo](#):
>
> It’s one of the design patterns in the Gang of Four.
> 
> It’s useful if you have some resource that must not be instantiated twice by the user, for instance, consider the following function:

Note that this kind of definition doesn’t really work that well in julia, as functions are not bound to instances of structs that they take as arguments. Simply instantiating `SettingsStruct` doesn’t make anything happen other than running the constructor function. If that is side effect free, it’s unnecessary to restrict creation of a new one (in fact, it may be preferable to do so, since being able to change settings on-the-fly and passing them around explicitly makes unit testing much easier and parallelizable).

Usually this is done with a `const SETTINGS = Ref(SettingsStruct(...))` if you want to be able to change the settings, or just `const SETTINGS = SettingsStruct()` if you don’t, though this approach will require careful handling in multithreaded code that also modifies `SETTINGS`, which is why it’s better for that usecase to explicitly pass the “secret state” around. If you only read from `SETTINGS`, having a `const` global is not wrong though.

> [@sapo](#):
>
> As you see, `test2` will fail, because the user has instantiated a wrong `d` .

If `Library` doesn’t even provide the second method, the user will get a `MethodError` instead, signaling that they’ve done something wrong.

> [@sapo](#):
>
> If `SettingsStruct` could be instantiated twice, the user could pass new  
> wrong values.

What do you mean by that? Are you thinking of keeping extra secret state per function call? If so, it’s much more user friendly to not do that and ask the user to pass in what you want to modify in the function.

---

<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:** [June 1, 2021, 12:13pm UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/6 "2021-06-01T12:13:41Z")

</div>

> [@sapo](#):
>
> Anywhere in the code, I am sure that `s` was not replaced by anyone, neither in interactive sessions.

Note that you cannot really ensure this with Julia. No matter how you plan to safeguard this, someone can always just `eval` into a module, etc.

I would just do

```julia
module Settings
export SETTINGS # note: only export
mutable struct _SettingsStruct
    a::Int64
    b::Int64
end
const SETTINGS = _SettingStruct(2, 3)
end

```

ie not export the constructor. Sure, the user can always access `SettingsStruct`, but that requires importing or an explicit module path, which should be warning enough, and also easy to grep the code for.

---

<div class="post-metadata">

**Author:** ![sapo](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@sapo](https://discourse.julialang.org/u/sapo)\
**Post date:** [June 6, 2021, 7:17pm UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/7 "2021-06-06T19:17:50Z")

</div>

Yep, probably, having the `const` keyword, that is the way to go…

---

<div class="post-metadata">

**Author:** ![sapo](https://avatars.discourse-cdn.com/v4/letter/s/ec9cab/32.png) [@sapo](https://discourse.julialang.org/u/sapo)\
**Post date:** [July 12, 2021, 8:39am UTC](https://discourse.julialang.org/t/implementing-singletons-for-configuration-variables/62177/8 "2021-07-12T08:39:39Z")

</div>

Actually, probably the best way is by using functions: [Revise and const values changed during a session? - #3 by sapo](https://discourse.julialang.org/t/revise-and-const-values-changed-during-a-session/64372/3)
