Vass
Vass

Reputation: 2820

How to initialize a composite type in Julia-lang and be accessible to all functions without it being passed as a function parameter?

In Julia Lang, how can a composite type have its parameter values allocated during runtime and be accessible to all the functions in the file?

I am looking for a feature similar to the 'static' keyword in Java. This is to avoid having to send the composite type in every function call as it is initialized from reading a file once and many functions rely on it; and not altered afterwards but the values are not known at compile time. ( I recall the usages of structs in Julia but am not sure if this would change anything )

Upvotes: 0

Views: 1088

Answers (1)

Bogumił Kamiński
Bogumił Kamiński

Reputation: 69829

  1. In Julia you can define global variables. Each Julia module (or baremodule) has its global scope. If you declare a global variable const then its type may not change (but its binding to a value possibly can).
  2. The second part of your question is mutability of such a global constant. If the type of the global constant variable is immutable (e.g. numbers, strings, structs, tuples, named tuples) then it will not be possible to change its value. However, it will be still possible to rebind the variable to a new value (as long as the new value has an appropriate type, we will get a warning that the binding has changed - see examples below).

A good example of such an approach in Julia Base is Base.GLOBAL_RNG variable (with the exception that it is mutable) - it holds a state of a default random number generator in Julia.

Here is a simple example using struct:

module E

struct A # immutable
    x::Int
end

const a = A(1) # global constant in module E

f() = println("a: $a")

function g()
     global a = A(10) # rebinding of a global variable requires global keyword
end

function h()
    a.x = 100
end

end # module

If you execute this in REPL you can test the behavior:

julia> E.a # we test the value of a global variable in module E
Main.E.A(1)

julia> E.f() # function f() from this module can access it
a: Main.E.A(1)

julia> E.h() # we cannot mutate fields of a
ERROR: type is immutable
Stacktrace:
 [1] setproperty! at .\sysimg.jl:9 [inlined]
 [2] h() at .\REPL[1]:16
 [3] top-level scope

julia> E.g() # but we can change the binding, we get a warning
WARNING: redefining constant a
Main.E.A(10)

julia> E.a
Main.E.A(10)    

julia> E.a = E.A(1000) # the binding cannot be changed outside the module
ERROR: cannot assign variables in other modules
Stacktrace:
 [1] setproperty!(::Module, ::Symbol, ::Main.E.A) at .\sysimg.jl:15
 [2] top-level scope

If you define a global constant in REPL then rebinding its value additionally emits a warning (here are some more examples with a global variable defined in REPL scope):

julia> global const z = E.A(5)
Main.E.A(5)

julia> z.x = 10
ERROR: type A is immutable
Stacktrace:
 [1] setproperty!(::Main.E.A, ::Symbol, ::Int64) at .\sysimg.jl:9
 [2] top-level scope

julia> z = E.A(2)
WARNING: redefining constant z
Main.E.A(2)

julia> z = "test" # we cannot change a type of const variable
ERROR: invalid redefinition of constant z

Here are the relevant sections of the Julia Manual:

EDIT: added missing global keyword in the definition of g function.

Upvotes: 2

Related Questions