Variables not recalculating while reloading modules

I have a module that i use to input some parameters (used in multiple functions etc, and I did not want to rewrite everywhere). They are lightly manipulated (basic scaling etc) and exported to various parts of a larger code.
Some of these parameters will be changed manually, and I wanted to run the program based on these updated parameters without restarting Julia (trying to avoid loading packages). Looks like the variable manipulations are not being carried out even when I use Revise.jl

Anyone have any suggestions

A MWE below

module Mymodule
x = 1
y = x*10
mygreeting() = "Hello, world!"

export x, y, mygreeting

The main file

using Revise
using Main.Mymodule

#accesssing from workspace directly
println(y)  #Does not update it's value

println(Main.Mymodule.y)    #Does not update it's value

The workflow in question

  1. Run the main file
  2. Update the module by x = 2 and mygreeting() = "Hello, Revised world!"
  3. Run main file again

The variable x and function mygreeting() gets updated to the new values, but y is still showing old value of 10.
Is there some way of updating the value in y

This is the behavior I see (v1.5.1)

julia> module Mymodule;
       x = 1; y = x*10
       export x, y

julia> using Main.Mymodule

julia> println(x)

julia> println(y)

julia> module Mymodule;
       x = 25; y = x*10
       export x, y
WARNING: replacing module Mymodule.

julia> using Main.Mymodule
WARNING: using Mymodule.x in module Main conflicts with an existing identifier.
WARNING: using Mymodule.y in module Main conflicts with an existing identifier.

julia> println(x)

julia> println(y)

julia> println(Mymodule.x)

julia> println(Mymodule.y)

The exported names conflict and therefore don’t get updated, but the internal module variables are accessible, and do update. If you start a new session, do you still see the behavior you described? (with or without using include should be the same I think)

I do not get this warning I’m guessing because of Revise.jl. since the module is in a separate file called “MyFile.jl” which revise is watching and updating on the go.

if I restart Julia session - All works as expected (variable j is updated) since Julia reads the file again fresh. I did not want to do it since it requires loading all the packages again which takes some time.

Wanted to check with the experts if I could get away by changing parameters without restarting Julia.

What happens if you explicitly say using Mymodule after changing/saving/re-including it?

Tested it myself with Revise. I see the same behavior as you. I would file an issue on Revise.jl.

Actually, this seems like a natural consequence of how Revise works. It doesn’t scan the entire module for inter-variable dependencies (it would have to do this as strings anway, since julia doesn’t store this information in any form; i.e. y = 10, not 10*x as far as julia is concerned) and it doesn’t reinclude all of the source from scratch, as that’s exactly what it’s trying to avoid. Variable capture in functions happens to be by binding, so if you made y() = 10*x you should indeed see it change along with x, but otherwise it is independent. A change like y = 11*x would redefine y.

I think the takeaway here is to design your global variable interface differently :sweat_smile:. Maybe as mutable structs, Dicts, etc… Also beware that global variables in julia are bad for performance unless they are const. Check out the performance tips of the manual for more info.

1 Like

Without Revise - I could not find any other way of getting around the name conflict. And having the freedom of using the names directly (without Module.x) was a nice feature that made Revise.jl a nice option

I was unsure if that is the expected behaviour of Revise itself. They only gave examples using functions inside of modules, and not on variables being manipulated like in this MWE.
I checked by changing x into an array, still the variable y is not being updated even when calling on lines includet and using

I edited my answer above, I think we were both typing at the same time!

1 Like

I agree this might be some of the Bad habits i have from MATLAB.
The ability to specify main parameters in a separate file and just importing them in functions that i needed is something i must unlearn then :wink:

I wanted to avoid global variables, since I do end up using same names in local scopes sometimes (x0 is initial state in one function whereas also initial guess in a different function and context), and the Julian way of inheriting into local scopes scared me off.

Do you mean be using the global keyword, or something else?
Not that I’m advocating for global variables (although if they’re const, there is no performance cost, and of course sometimes they’re necessary), but it is very easy to capture globals:

julia> const α = 11

julia> f(x) = x + α
f (generic function with 1 method)

julia> f(1)

The easiest way to get what you want is:

  • put your functions in one file, and includet it once;
  • put your computations in a separate file, and include it (no “t”) each time you want to rerun the computations

You can even use Revise’s entr to automatically re-include the computations file any time that file or your code file changes.

1 Like