Pass runtime variables to module's __init_() function

Julia docs point out that one can define an init() function for a module, which is run when the module is imported.

It would be interesting to have a possibility to pass some runtime variables to the init function.
Then, we can modify the syntax of using Module or import Module to pass along the parameters which will be processed by init function.

This is unlikely to be a good idea because all dependents share the same copy of the module, so it’s unclear what would happen if they call it with different arguments. If you elaborate on your use case, somebody may be able to point you to the recommended customization mechanism.

2 Likes

I am thinking about extending Unitful.jl.
I should point out that I am not a maintainer of the package, but I am curious about the ways it can be improved (no disrespect to the real maintainers of the package).

There, @u_str macro is defined, which takes the string and looks up the units corresponding to Symbol(string) in a number of modules. By default, it looks in the module Unitful itself.

Right now, Unitful supports only SI unit system. I would like to add more unit systems. However, different unit systems define the same units in a different manner. To avoid the ambiguity in the lookup of the units, I am thinking about the following thing:

  • organize different unit systems in different submodules
  • have @u_str by default use the submodule which is referenced in a global variable inside Unitful module
  • provide a function which allows to change this variable to point to the submodule of choice

With this approach, the users of Unitful.jl would be able to choose different unit systems.
However, there are other packages that build upon Unitful.jl by defining new units. For any of these packages, the choice of the unit system must occur between the point where Unitful.jl is imported and the point where the new units are defined.

If there were a possibility to pass runtime variables to init, the user of these other packages can still choose a unit system, and this choice can be tansmitted all the way down to Unitful.jl.

I can put it in more abstract terms.

Let’s say I have a module A with a predefined set of global states. I also have module B that imports A. Behaviour of module B depends on the global state of module A on the moment of import.
Question: how do I control the global state of module A in which it is imported into module B, from module C which imports module B?

Unfortunately you can’t, unless you want to also fight a battle with module D which also imports module A somehow. This is, in a nutshell, the whole problem with trying to mutate shared global state.

As an alternative, what if you were to create your own module which looks something like:

module MyUnitSystem

using Unitful

macro u_str(str)
  # parse this string however you want, returning units in your particular system of choice
end

end

This avoids the need to modify the internals of Unitful in any way, and it should make it easy for users to decide whether they want your units (by doing using MyUnitSystem: @u_str ) or the default one (via using Unitful: @u_str)

1 Like

In principle, different unit systems can be used interchangeably. If we have a package UnitfulExtension that depends on Unitful, the dependence on Unitful can be replaced with dependence on MyUnitSystem (provided MyUnitSystem exports the same stuff as Unitful does). However, users of UnitfulExtension will have to stick with whatever the choice that its mainainers maid. Or make a copy of UnitfulExtension which imports MyUnitSystem in place of Unitful.