In this simple example, if I need a counter for a while loop, how to avoid using global variable? Can I initialize something inside while scope?
i = 0
while i < 10
global i
i += 1
k = i
end
In this simple example, if I need a counter for a while loop, how to avoid using global variable? Can I initialize something inside while scope?
i = 0
while i < 10
global i
i += 1
k = i
end
Most of the time, for
loops are more appropriate than while
loops:
for i = 0:9
k = i
end
However, if you must use while
, you can create a local scope with the let
block and nest the loop within it:
let i = 0
while i < 10
k = i
i += 1
end
end
Note that the global is only needed if you are running the loop in the global scope of an included script, which probably is a bad idea.
yes… but this is like creating a new scope inside global to use it for the separate section of a code. Not really smth very good i my case. But thx)
Actually you’re right this is important. I probably need to mention, that I’m running this loop inside module.
module mod
i = 0
while i < 10
global i
i += 1
k = i
end
end
The general practice is to put everything into functions. Then you execute the function.
How that would be as a function for a while loop? Can you write a short example pls?
And how this global i
will be avoided?
For example:
function calc_k()
i = 0
while i < 10
i += 1
k = i
end
return k
end
could you please tell why while
inside function can work without global i
and while
inside module cannot?
This is the section of the docs explaining the relevant scoping rules:
https://docs.julialang.org/en/v1/manual/variables-and-scoping/#Local-Scope
In particular, see rule 3 in the list, titled “Soft scope”, and the example beginning with the text
Next, let’s consider the body of
sum_to_def
extracted into global scope
The first thing is that in a loop where a variable is assingned, like this:
i = 1
for j i n 1:3
i = 2
end
println(i)
there is a possible ambiguity associated with i
referring to the i
outside the loop, or to the a new i
created by the scope of the loop iteration.
In Julia, this ambiguity can have important performance implications depending on whether i
is a non-constant global variable or a variable in a local scope, where its type can be inferred upon compilation.
If the whole block is inside a function (or a let
block, for example), the type of i
can be inferred (in general) then i
is local to the scope of the function, can be type-stable and everything will be optimized accordingly. Thus, there are no issues associated with that pattern.
If, on the other side, the code is in a global scope, the performance will be very different depending on the possibility of type-inferring i
. Julia therefore wants to discourage people from writing code in global scope, particularly code that is aimed to be performant. Thus, if the user wants to write a loop in global scope, he/she has to be explicit aware that of that ambiguity and possible implications, and it was decided that requiring an explicit global annotation was a good choice.
Later, in v1.5, that requirement was removed from code typed directly into the REPL, because otherwise one could not copy-paste code from the body of functions to the REPL directly, and that was annoying. This having minor importance since nobody writes performant critical code outside functions in the REPL directly.
I think that is more or less the story of it. It is as tradeoff between usability and promoting good practices of Julia programming.
thank you @lmiq for this thoughtful explanation