# ANN: ScopedSettings - ScopedValues with malleable global values

**URL:** <https://discourse.julialang.org/t/ann-scopedsettings-scopedvalues-with-malleable-global-values/130946>\
**Category:** Package Announcements\
**Created:** [July 22, 2025, 3:35pm UTC](https://discourse.julialang.org/t/ann-scopedsettings-scopedvalues-with-malleable-global-values/130946 "2025-07-22T15:35:58Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![oschulz](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/oschulz/32/2998_2.png) [@oschulz](https://discourse.julialang.org/u/oschulz)\
**Post date:** [July 22, 2025, 3:35pm UTC](https://discourse.julialang.org/t/ann-scopedsettings-scopedvalues-with-malleable-global-values/130946/1 "2025-07-22T15:35:58Z")

</div>

I recently registered [ScopedSettings](https://github.com/oschulz/ScopedSettings.jl).

Thanks to @vchuravy we now have `ScopedValues` (natively as `Base.ScopedValues` since Julia v.11 and via the fallback package [ScopedValues](https://github.com/vchuravy/ScopedValues.jl) for earlier Julia versions).

ScopedValues are a powerful new way to do “dependency injection” in Julia, and handle “preferences” in a scope-dependent way. One issue though is that the global/default value of a `ScopedValue` is fixed. In the past, we often used a global `Ref` or so for default settings in packages. Those are easy to change/override, but don’t provide scoping. While `ScopedValue` doesn’t allow for an easy global change/override.

`ScopedSetting` builds on `ScopedValue` to combine these two approaches: The global/default value can be manipulated/overridden (thread-safe), and it can be a fixed value or the result of a function that computes it on the fly. But in scopes, it behaves like a `ScopedValue`:

```julia
using ScopedSettings
some_setting = ScopedSetting(42)
some_setting isa ScopedSetting{Int}

```

is accessed like a `ScopedValue`

```julia
some_setting[] == 42

```

it’s global default value can be overridden

```julia
some_setting[] = 11
some_setting[] == 11

```

and can also be restored to the original default value

```julia
some_setting[] = nothing
some_setting[] == 42

```

The global default can also be function (without arguments):

```julia
other_setting = ScopedSetting(()->rand())
[other_setting[], other_setting[], other_setting[]] # random values
other_setting[] = 1.2 # override
other_setting[] == 1.2 # no more random values

```

Like with a `ScopedValue`, scoped settings can be set to different values for different scopes:

```julia
@with some_setting => 33 other_setting => 5.2 begin
    # Within this scope, we have
    some_setting[] == 33 && other_setting[] == 5.2
end

with(some_setting => 33, other_setting => 5.2) do
    # Within this scope, we have
    some_setting[] == 33 && other_setting[] == 5.2
end

# Globally we still have

some_setting[] == 42
other_setting[] == 1.2

```

ScopedSettings re-exports `ScopedValues.@with` and `ScopedValues.with(...)`. You can mix `ScopedSetting` and `ScopedValue` objects in `@with` expressions

and `with(...)` calls.

To base `ScopedSetting` default values on [package preferences](https://github.com/JuliaPackaging/Preferences.jl) and environment variables, ScopedSettings provides `GetPreference{T}` function objects:

```julia
setting_foo = ScopedSetting(GetPreference(SomePackage, "foo", 42))
setting_bar = ScopedSetting(GetPreference(SomePackage, "bar", :green))

setting_foo[] == either_envvar_or_preference_value_or_42
setting_bar[] == either_envvar_or_preference_value_or_green

@with setting_foo => 11 setting_bar => :blue begin
    # Different values within this scope
    setting_foo[] == 11 && setting_bar[] == :blue
end

# Original values outside of the scope
setting_foo[] == either_envvar_or_preference_value_or_42
setting_bar[] == either_envvar_or_preference_value_or_green

```

In the global scope, the value of `setting_foo[]` will depend on the `LocalPreferences.toml` files (if any) in your `LOAD_PATH` that have entries like

```toml
[SomePackage]
foo = 33
bar = "turquoise"

```

and environment variables like `SOMEPACKAGEJL_FOO` and `SOMEPACKAGEJL_BAR` (environment variables take precedence over preferences).
