Global variables within 2 files

Hello!

How can I declare a global variable that is shared between two files?

File1.jl

import("File2. jl") 

function1 test() 
    close=false
    a=0
    If a>0
        close = true
    end
end

File2.jl

function2 test2() 
    If close == true
        b=0
    end
end

The shared variable is close=true or false

Thank you!

There is nothing telling Julia that close is global. Defining close in at the global level before importing File2.jl should ensure that Julia knows where close is defined.

File1.jl

close = true

import("File2.jl")

function1 test()
    close=false
    a=0
    if a>0
        close = true
    end
end

File2.jl

function2 test2()
    if close == true
        b=0
    end
end
1 Like

Please quote your code when you ask a question: PSA: how to quote code with backticks

It is a very bad idea to (i) use global variables, and (ii) especially a bad idea to share them between different files!

Instead, pass the variables as arguments to your functions. If you have many parameters, wrap them up into a type, e.g. using Parameters.jl.

3 Likes

@dpsanders i think is imposible to pass the variable as arguments to functions when function1 from File1.jl and function2 from File2.jl is running on different threads continuously. The condition for function2 to stop is given by the function1. Ex: the function1 will continously readline() and if I write in console the string “stop” then the function2 will stop, if not the function2 will run continuously.

Ah well you didn’t mention threads in your original question.

That sounds like (I believe) a use-case for Channels:

https://docs.julialang.org/en/v1/manual/parallel-computing/#Channels-1

1 Like

@pixel27 I tried your method and didn’t work.

File1.jl

import Base.Threads.@spawn

include("File2.jl")

close = false

function test()
	while true
		word = readline()
		if word == "close"
			close = true
			println("you choose to close")
		end
	end
end


t1 = @spawn test()
t2 = @spawn runF()
fetch(t1)
fetch(t2)

File2.jl

function runF()
	for i in 1:50
		println(close)
		sleep(5)
		if close == true
			println("closed")
			break
		end
	end
end

when run the File1.jl the results is
false
false
false
…

You defined close after you imported “File2.jl”. When defining functions Julia compiles the function before executing it. So if you did this:

function parent()
    function child(a)
         b = a
    end

    b = "abc"
   
    child("xyz")

    println(b)
end

When it’s compiled Julia will notice that “b” was defined in the parent scope so the child() function will know to set “b” in the parent scope, rather than “b” in the child scope. So with this example it will print “xyz”.

When executing top level commands in a file, Julia does not compile the whole file then execute it, it runs like a script, i.e. one line at a time. Which means at the time it included “File2.jl” there was no definition for “close” yet, that line has not been processed yet. Which means this:

function child(a)
     b = a
end

b = "abc"
   
child("xyz")

println(b)

Will actually print “abc” even though it’s the SAME code that was in the parent function above. This is one of the little gotchas with Julia. :slight_smile:

3 Likes

It works now ! Thank you all !

In the File1.jl you need to specify that variable that is changed is global

if word == "close"
			global close = true
			println("you choose to close")
			println(close)
		end

So you need to specify “global close = true” instead of “close = true”

Maybe one thing to keep in mind is that files don’t really have semantic significance in Julia. Splitting things into two files is fine but it’s just a matter of organization; if you do

A = ...

include(“FileB.jl”)

...

then it’s just the same as if you copy and paste the contents of “FileB.jl” into where the include statement is.

2 Likes

Do you mean all global variables or globals in Main? Because there are many good uses for a specific module global variable. And if the module is very big, I often break it into many files that make reference to the same module global variable.

The general advice in software engineering is to avoid global variables whenever possible, since it makes understanding the code much harder.

This, and the performance penalty of global variables in Julia (as long as Type annotations in global scope · Issue #964 · JuliaLang/julia · GitHub is not implemented).

2 Likes

They do not have a performance penalty if you fix the binding by using const. And by using const GLOBAL = RefValue{TYPE_T}(OBJECT_OF_TYPE_T) you have a global of any type you want that you can change the value and has no performance problems.

2 Likes