# Package Development: Why is Ref needed to pass a global constant to a function?

**URL:** <https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566>\
**Category:** General Usage\
**Tags:** constants, package-dev, ref\
**Created:** [November 13, 2024, 1:39am UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566 "2024-11-13T01:39:02Z")\
**Posts on this page:** 14\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [November 13, 2024, 1:39am UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/1 "2024-11-13T01:39:03Z")

</div>

I currently have the following setup (which works great) but somehow seems inelegant:

`src/MyPackage.jl`

```julia
module MyPackage
include("mysrc.jl")
const CONFIG = Ref{Config}()
end

```

`src/mysrc.jl`

```julia
@with_kw struct Config
    a :: Int64 = 0
    [...]
end

function myfunc()
    @unpack_Config CONFIG[]
    [...]
end

```

`scripts/myscript.jl`

```julia
const CONFIG[] = Config();
res = myfunc()

```

What exactly am I telling the compiler? Is there a reason for no keyword like `container const` to accomplish the same thing as `Ref{}` and the brackets?

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [November 13, 2024, 1:48am UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/2 "2024-11-13T01:48:08Z")

</div>

I think many packages do something like

```julia

module M

struct Config
    ...
end
const config = Ref{Config}()

f(arg1) = f(CONFIG[], arg1)
function f(config::Config, arg1)
    #logic with config and arg
end
end

```

That way, you can bypass the default config when you need to without changing it for all calls.

It’s also worth noting that you could use `ScopedValues` introduced in 1.11 to make dynamic but const-global like variables instead of large config structs if you’re always unpacking anyway.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [November 13, 2024, 6:20am UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/3 "2024-11-13T06:20:18Z")

</div>

Not sure why a `Ref` would be necessary for this pattern to work though?

In a slightly different setting, Preferences.jl might be useful too.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [November 13, 2024, 6:23am UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/4 "2024-11-13T06:23:00Z")

</div>

I think the `Ref` pattern originates in a time where Julia didn’t have typed globals. Nowadays, typed globals should behave (almost?) identical to that pattern.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [November 13, 2024, 12:08pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/5 "2024-11-13T12:08:57Z")

</div>

Ref also doesn’t need to be initialized at parsing time too. But I agree that typed globals are fine in general!

---

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [November 13, 2024, 6:43pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/6 "2024-11-13T18:43:25Z")

</div>

Maybe its time I just put this on github, but for now I’ll continue with the pseudo-package. Based on the comments I tried:

```julia
module MyPackage
include("mysrc.jl")
# const CONFIG = Ref{Config}()
end

```

```julia
@with_kw struct Config
    a :: Int64 = 0
    [...]
end

function myfunc()
    @unpack_Config CONFIG
    [...]
end

```

```julia
const CONFIG = Config();
res = myfunc()

```

I get the error:

```julia
julia> res = myfunc()
nested task error: UndefVarError: `CONFIG` not defined in `MyPackage`

```

If I instead do:

```julia
module MyPackage
include("mysrc.jl")
const CONFIG :: Config = Config()
end

```

Then the values cannot be modified in a script:

```julia
julia> CONFIG.a = 10
ERROR: setfield!: immutable struct of type Config cannot be changed

julia> CONFIG = Config(a = 10)
WARNING: redefinition of constant Main.CONFIG. This may fail, cause incorrect answers, or produce other errors.

```

Can anyone clarify what you mean?

---

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [November 13, 2024, 7:03pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/7 "2024-11-13T19:03:09Z")

</div>

This seems to work though. In the package module (no `cons`t):

`CONFIG :: Config = Config()`

Then declare it const _in the script_:

```julia
const CONFIG = Config(a = 10);
res = myfunc()

```

I’ll have to check its actually using that new value, but that seems much cleaner.

EDIT:  
It doesn’t work. The original value assigned in the module is still used.

---

<div class="post-metadata">

**Author:** ![gdalle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gdalle/32/27854_2.png) [@gdalle](https://discourse.julialang.org/u/gdalle)\
**Post date:** [November 13, 2024, 7:03pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/8 "2024-11-13T19:03:36Z")

</div>

It really seems like a weird pattern. Can’t you use something like Preferences.jl?

---

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [November 13, 2024, 7:25pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/9 "2024-11-13T19:25:38Z")

</div>

Maybe, the main problem is I’m porting a C++ program that reads in a few text files for configuration. I’m trying to keep it backwards compatible.

I can also foresee a use for running multiple julia sessions with different config values at the same time.

But I definitely need to look into `Preferences.jl`.

---

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [November 13, 2024, 9:58pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/10 "2024-11-13T21:58:46Z")

</div>

> [@mrufsvold](#):
>
> `const CONFIG:: = Ref{Config}()`

Can you explain/link what those colons are doing there? I haven’t seen that before.

---

<div class="post-metadata">

**Author:** ![mrufsvold](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mrufsvold/32/31600_2.png) [@mrufsvold](https://discourse.julialang.org/u/mrufsvold)\
**Post date:** [November 13, 2024, 11:14pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/11 "2024-11-13T23:14:46Z")

</div>

Just a typo. I fixed it now. Originally I was writing it out as a typed global!

---

<div class="post-metadata">

**Author:** ![sadish-d](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sadish-d/32/48058_2.png) [@sadish-d](https://discourse.julialang.org/u/sadish-d)\
**Post date:** [November 15, 2024, 5:40pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/12 "2024-11-15T17:40:58Z")

</div>

`Ref` allows you to change configuration.

```julia
struct Config
    v::Bool
end
const config = Ref{Config}(Config(true))

f(c::Config, x::Bool) = c.v == x
f() = f(config[], true)

@assert f() # with original configuration
config[] = Config(false) # change configuration
@assert !f() # with changed configuration

```

---

<div class="post-metadata">

**Author:** ![Tetrakai](https://avatars.discourse-cdn.com/v4/letter/t/4da419/32.png) [@Tetrakai](https://discourse.julialang.org/u/Tetrakai)\
**Post date:** [November 15, 2024, 7:39pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/13 "2024-11-15T19:39:06Z")

</div>

Thanks, it felt like I was using a workaround “trick” though.

I was wondering about why there isn’t a more elegant way (or more likely I missed it).

`Preferences.jl` may be a solution but even that requires an entire new file. I’m sure theres some history in github comments I don’t know how to find.

---

<div class="post-metadata">

**Author:** ![sadish-d](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/sadish-d/32/48058_2.png) [@sadish-d](https://discourse.julialang.org/u/sadish-d)\
**Post date:** [November 15, 2024, 7:47pm UTC](https://discourse.julialang.org/t/package-development-why-is-ref-needed-to-pass-a-global-constant-to-a-function/122566/14 "2024-11-15T19:47:05Z")

</div>

@mrufsvold pointed out `ScopedValues` in Julia 1.11. Maybe that’s what you’re looking for? I think it was around as its own package pre 1.11.
