# Dynamic include file selection with world age constraints in Julia 1.12 - alternatives to conditional include?

**URL:** <https://discourse.julialang.org/t/dynamic-include-file-selection-with-world-age-constraints-in-julia-1-12-alternatives-to-conditional-include/133581>\
**Category:** General Usage\
**Tags:** question, world\_age\
**Created:** [October 31, 2025, 4:06pm UTC](https://discourse.julialang.org/t/dynamic-include-file-selection-with-world-age-constraints-in-julia-1-12-alternatives-to-conditional-include/133581 "2025-10-31T16:06:41Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![sfuerst](https://avatars.discourse-cdn.com/v4/letter/s/3da27b/32.png) [@sfuerst](https://discourse.julialang.org/u/sfuerst)\
**Post date:** [October 31, 2025, 4:06pm UTC](https://discourse.julialang.org/t/dynamic-include-file-selection-with-world-age-constraints-in-julia-1-12-alternatives-to-conditional-include/133581/1 "2025-10-31T16:06:41Z")

</div>

Hi everyone,

I’m facing a challenge with Julia 1.12’s stricter world age semantics. I have a pattern where I conditionally include different implementation variants based on configuration, but this no longer works in Julia 1.12.

Here’s a minimal example of what I’m trying to achieve:

```julia
function include_switch(a_or_b)
    mktempdir() do dir
        write(joinpath(dir, "fileA.jl"), "fooA() = :a")
        write(joinpath(dir, "fileB.jl"), "fooB() = :b")
        func = if a_or_b == :a
            include(joinpath(dir, "fileA.jl"))
            fooA
        else
            include(joinpath(dir, "fileB.jl"))
            fooB
        end
        # foo is registered in my modular system for later use, e.g. 
        # register_substep_imp(:prepare_sim, func, PRIO_NORMAL)
    end
end        

include_switch(:a)

```

This gives me:

```julia-auto
WARNING: Detected access to binding `Main.fooA` in a world prior to its definition world.
  Julia 1.12 has introduced more strict world age semantics for global bindings.
  !!! This code may malfunction under Revise.
  !!! This code will error in future versions of Julia.
Hint: Add an appropriate `invokelatest` around the access to this binding.

```

The context is a modular model system where different variants can be selected through configuration. The `invokelatest` suggestion doesn’t work here since I’m not calling the function yet - I just want to register it in my system for later use.

What’s the recommended approach for this kind of dynamic file selection pattern in Julia 1.12?

Thanks for any insights!

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 31, 2025, 4:54pm UTC](https://discourse.julialang.org/t/dynamic-include-file-selection-with-world-age-constraints-in-julia-1-12-alternatives-to-conditional-include/133581/2 "2025-10-31T16:54:16Z")

</div>

`eval` messing with global names from inside methods wasn’t good practice prior to 1.12 either, `const` variables are a bit more obvious:

> **1.11.7**
>
> ```julia-auto
> julia> function foo(i)
> eval(:(const a = $i))
> a
> end
> foo (generic function with 1 method)
> 
> julia> foo(0)
> 0
> 
> julia> foo(1)
> WARNING: redefinition of constant Main.a. This may fail, cause incorrect answers, or produce other errors.
> 1
> 
> julia> foo(2)
> WARNING: redefinition of constant Main.a. This may fail, cause incorrect answers, or produce other errors.
> 2
> 
> julia> foo(3)
> WARNING: redefinition of constant Main.a. This may fail, cause incorrect answers, or produce other errors.
> 3
> 
> ```

> **1.12.1**
>
> ```julia-auto
> julia> function foo(i)
> eval(:(const a = $i))
> a
> end
> foo (generic function with 1 method)
> 
> julia> foo(0)
> WARNING: Detected access to binding `Main.a` in a world prior to its definition world.
> Julia 1.12 has introduced more strict world age semantics for global bindings.
> !!! This code may malfunction under Revise.
> !!! This code will error in future versions of Julia.
> Hint: Add an appropriate `invokelatest` around the access to this binding.
> To make this warning an error, and hence obtain a stack trace, use `julia --depwarn=error`.
> 0
> 
> julia> foo(1)
> 0
> 
> julia> foo(2)
> 1
> 
> julia> foo(3)
> 2
> 
> ```

Function names are `const` too, but you’ve been getting away with this because evaluating more method definitions for the same name is not a reassignment. The problem here is the conditional existence of global names, and it’s clashing with 1.12’s tighter implementation of them. If you want to treat modules as `Dict{Symbol, Any}`, you need to reference the module AND use `@invokelatest` to access the uncertain name:

```julia-auto
julia> function bar(i)
         eval(:(b = $i))
         @invokelatest (@ __MODULE__ ).b
       end
bar (generic function with 1 method)

julia> bar(0)
0

julia> bar(1)
1

julia> bar(2)
2

```

Your MWE works with the according changes, but I feel it’s important to point out that the global names `fooA` and `fooB` don’t seem necessary, and conditional global names are not good practice in general. What do you need out of the implementation variants exactly?

---

<div class="post-metadata">

**Author:** ![sfuerst](https://avatars.discourse-cdn.com/v4/letter/s/3da27b/32.png) [@sfuerst](https://discourse.julialang.org/u/sfuerst)\
**Post date:** [October 31, 2025, 6:17pm UTC](https://discourse.julialang.org/t/dynamic-include-file-selection-with-world-age-constraints-in-julia-1-12-alternatives-to-conditional-include/133581/3 "2025-10-31T18:17:45Z")

</div>

Okay, got it, I can use getfield as function to call via @invokelatest.

Regarding the good practice I want to point out, that functions like `include_switch` are only called once per Julia session. And e.g. :a or :b from the MWE could be

> **[src/modules/reconsider\_mob\_avail/social\_theory\_rational.jl · main · steffef69...](https://git.imp.fu-berlin.de/steffef69/momotmo/-/blob/main/src/modules/reconsider_mob_avail/social_theory_rational.jl)**
>
> Freie Universität Berlin Mathematik und Informatik

or

> **[src/modules/reconsider\_mob\_avail/social\_theory\_bounded.jl · main · steffef69...](https://git.imp.fu-berlin.de/steffef69/momotmo/-/blob/main/src/modules/reconsider_mob_avail/social_theory_bounded.jl)**
>
> Freie Universität Berlin Mathematik und Informatik

That I use different function names depending on the selected file has the advantage, that I can easily see, what is include in the current session (and in what order it is called):

```julia
julia> list_everything()
pre_init
--------
demographic__core: set_demographics_rnd_seed (PRIO_FIRST)
population__with_regiostar: initialize_regiostar! (PRIO_NORMAL)
population__with_pt_stop_distances: read_pt_stops (PRIO_NORMAL)
...

reconsider_mob_avail: rational_decision (PRIO_NORMAL)

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 31, 2025, 6:36pm UTC](https://discourse.julialang.org/t/dynamic-include-file-selection-with-world-age-constraints-in-julia-1-12-alternatives-to-conditional-include/133581/4 "2025-10-31T18:36:03Z")

</div>

> [@sfuerst](#):
>
> That I use different function names depending on the selected file has the advantage, that I can easily see, what is include in the current session

That does make sense from an interactive standpoint. Still, you were working around method table state as part of world age before, and now you have to work around global namespace state as well. You could dodge the latter with a manual global cache of `Dict{Symbol, Function}`, but that would involve some really custom metaprogramming especially for multimethod functions. At that point, using a module and `@invokelatest` doesn’t even seem that bad. If you don’t have a dedicated module though, you should; the MWE putting names in `Main` is very uncomfortable.

You could use RuntimeGeneratedFunctions.jl to throw unique method bodies into a preexisting `@generated` method definition to dodge world age and manually cache them in a global `Dict{Symbol, Any}` for retrieval later. But that does come with the `@generated` limitation of no nested functions (including `do` blocks and comprehensions) and a hefty amount of refactoring, so this is probably something to know and not do for now.
