For /While loops create a local scope. Thus, if you’d like to write a function the outputs variables defined inside of the for /while loop, one must declare these variables as global beforehand, or use a let wrapper.
The contradiction I see is that Julia has a hard time compiling code with global variables. I’ve seen this in my own code as I try to achieve type stability.
My questions are:
How can I write loops in a way that is type stable, even though I must declare globals?
Will declaring a global variable outside of a for loop have a significant impact on the performance of my code?
The easiest way to do this is by writing a function, for loops should be inside functions, and you can either create the variable inside the function, or make a mutating function that takes a variable.
You should not use globals at all, write everything inside functions:
function myloop(y)
x = 0
for i in 1:10
x += i*y
end
return x
end
no need for declaring anything global. And you pass the parameters required to that function.
An additional comment: In Julia a good advice for newcommers is never, ever, use the global keyword. If you feel that you cannot avoid using it, ask for advice.
I think the structure of my code makes this a little more tricky. Here is sample code written for legibility (I’m new, so sorry if its inefficient style). Note that each function call is type stable.
function myloop(x_mat)
trig = 0
cnt = 1
T_step = 100
tol = 1e-6
global Q
global x
global ν
global s
global T_bar
while trig ==0
x_in = x_mat[:,1:T_step*cnt]
x,ν,s = simulate_data(x_in)
Q = compute_Q(x,ν,s)
if Q[end]<tol
trig = 1
T_bar = T_step*cnt
else
cnt += 1
end
end
return Q, x, ν, s, T_bar
end
Pass all those “global” variables as parameters to your function. For example with a named tuple:
julia> function f(x_mat,p)
Q, x = p.Q, p.x # In 1.7 you can write this as (; Q, x) = p
x_mat = x_mat*Q + x
return x_mat
end
f (generic function with 1 method)
julia> p = (Q = 1.0, x = 2.0); x_mat = 2.0;
julia> f(x_mat,p)
4.0
Note that here, if x, v and s are immutable (meaning, they are not arrays), declaring them “global” or not is the same, you are just redefining them again here.
Maybe your question is of another sort: How to use the value of a variable that was created inside a loop, outside the scope of the loop. Then, there are two options: initialize the value with any value outside the loop, or declare it local (I prefer this one):
julia> function myloop()
local m
for i in 1:2
m = i
end
return m
end
myloop (generic function with 1 method)
julia> myloop()
2
julia> function myloop()
m = 0
for i in 1:2
m = i
end
return m
end
myloop (generic function with 1 method)
julia> myloop()
2
Looking at your code there, I think is what you actually want, to declare all those variales as local to the scope of the function, to use the values they acquire in the loop and return them.
Yes! Thank you so much for working through my ill-posed questions, and getting at the heart of the matter. This is what I was looking for, as x, v, s are all arrays.
Nice, next step is to realize that you are allocating new arrays at every iteration of the loop, as the result of your simulate function. This will be somewhat slow. The same for Q, and for x_in. Ideally you want to allocate the arrays outside the loop and make those function mutate their values.