How to avoid using global variable in while scope?

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.

See: Scope of loops · JuliaNotes.jl

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.

6 Likes

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
1 Like

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

1 Like

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.

7 Likes

thank you @lmiq for this thoughtful explanation