Thank you so much! Today I have prepared a little test comparing your solution and another idea I had involving mutable structs. Your solution is by far the best (even better the not-working one).
Here the code and tests:
# A.jl
module A
# METHOD 1
# the following works but are not re-evaluated by Revise
const a = 5
b = 5
# METHOD 2
# functions are re-evaluated by Revise when they are changed
const c() = 5
d() = 5
# METHOD 3
mutable struct S
vars::NamedTuple
function S()
# the following ensures that S cannot be reinstantiated without explicit
# usage of `eval`
isdefined(S, :s) && error("Cannot instantiate S twice")
return new()
end
end
# `const` ensures that the reference to the object will always be the same
const s = S()
# an easier way to get the settings
function getS()
return s.vars
end
# defining fields in a function allows Revise to re-evaluate it when settings
# are changed
function init()
s.vars = (a = 5, b = 5)
end
end
# B.jl
module B
using Main.A: a, b, c, d, getS
function test1()
r = 0
for i in 1:1000
r += a + b
end
return r
end
function test2()
r = 0
for i in 1:1000
r += c() + d()
end
return r
end
function test3()
s = getS()
r = 0
for i in 1:1000
r += s.a + s.b
end
return r
end
end
# C.jl
module C
using BenchmarkTools
using Main.B: test1, test2, test3
using Main.A: init
function main()
init()
println(@btime test1())
println(@btime test2())
println(@btime test3())
end
end
# D.jl
using Revise
includet("A.jl")
includet("B.jl")
includet("C.jl")
And here the tests:
julia> include("D.jl");
julia> C.main()
k 30.400 μs (958 allocations: 14.97 KiB)
12000
1.492 ns (0 allocations: 0 bytes)
12000
62.388 μs (958 allocations: 14.97 KiB)
12000
julia> C.main() # re-run after having changed the settings
30.289 μs (958 allocations: 14.97 KiB)
12000
1.492 ns (0 allocations: 0 bytes)
10000
62.629 μs (949 allocations: 14.83 KiB)
10000
As you see, method 1 doesn’t work on re-evaluation, method 3 works but is 2x slower, while method 2 works and is 20.000x faster