Usage of loops for defining new variables

Hi!

I have a rather simple question, which probably boils down to my non-familiarity with the language.

I am translating a code from Matlab and was getting a constant error about one variable not defined within a
loop. Since the code is rather cumbersome I simplified it to a stupid example, which makes no sense but it serves the purpose:

for j =  1:2
    xtemp = j*ones(3,1);
end

When I execute the code, xtemp does not get defined and is not a variable in the workspace. What is the reason, what am I doing wrong?

I have Julia 1.0.0. running on the latest Atom (1,29) with Juno.

Thanks!

Your loop is introducing a new scope; that is, the xtemp you’re creating only exists within that for loop and can’t be accessed outside of it.

However, if you have an xtemp outside of the loop within your function, the loop will “inherit” that binding and the outer xtemp will be updated:

julia> function foo()
         x = 1
         for i in 1:10
           x = i
         end
         @show x
       end
foo (generic function with 1 method)

julia> foo()
x = 10

When you’re executing code at the command line, you’re not inside a function. In that case, you need to explicitly tell Julia that your xtemp is global:

julia> x = 1
1

julia> for i in 1:10
         global x = i
       end

julia> x
10
1 Like

I think the way of coding a loop inside a function and in global scope could be the same. Recently I got a hard time explaining the use of global inside loops to students that are learning programming.

1 Like

You are not alone in that sentiment: https://github.com/JuliaLang/julia/issues/28789

2 Likes

Thank you for the insight, this is interesting and I have to read more about scopes.

I suspected there might be something like this so I tried defining the variable outside of the loop and that did not help, that is why I posted. I tried your suggestion as well and if it is in the file (i.e. not in a function) it still does not work. Is that the intended behaviour?

xtemp = zeros(3,1);
for j =  1:2
   xtemp = j*ones(3,1);
end

xtemp is still [0.0;0.0; 0.0]

xtemp = zeros(3,1);
for j =  1:2
    global xtemp
    xtemp = j*ones(3,1);
end

xtemp = [2.0; 2.0; 2.0].

I thought it was always a good idea to avoid global variables but I saw that from the thread in your link. I will read the section about scopes because several questions pop up with this behaviour. For example, if I define the variable as global, is it global in terms of that it is simply available outside of the loop or is it global in terms of that its type may change in any time and therefore is suboptimal regarding performance?

It seems I have to define all variables within loops as global, or? I tested writing a function after the loop above with xtemp defined as global and within that function xtemp was available, i.e. xtemp really was a global variable available in the space of functions and I am not sure this is a desired behaviour for me. I mean, that would mean that if I define, say “x” in a loop as global, then every function with “x” in it might encounter problems, if I understand the manual correctly, which also mentions this.

I read through the documentation and the other topics, i.e.

https://stackoverflow.com/questions/51930537/scope-of-variables-in-julia/

and the link provided by @rdeits.

Yes, I also did feel it is counter intuitive, simply because I have never thought a for/while loop the same as a function, i.e .to have its own variable space. In other words, I simply did not expect
x(1) = 1
x (2) = 2
and
for i = 1:2
x[i] = i;
end
to have different behaviour, I simply saw the for loop as an easier way not to have to write the same thing many times. Technically this is the way a function works, so it makes sense once I think about it, it was a point I have never thought about.

However, neither the documentation, nor the links provide an answer to my question regarding speed and global variables - is declaring a variable as global in a loop “bad” in terms of leading to performance loss? I mean in terms of the typical arguments against global variables (in relation to variable type and machine code optimization), e.g. here or here. It is noted in the manual, that changing the values of global variables is not recommended but then, isn’t changing the value of a variable iteratively the main purpose of loops?

If it does, than this speaks for avoiding loops or am I missing something? I do a lot of Markov Chain Monte Carlo in my work where loops are essential. Every step of my program depends typically on the previous iteration and within a loop I change most of the variables of interest, i.e. they all have to be global.

Put your code in functions.
Within functions, you can say

function foo()
    reassigned = false
    for i in 1:1
        reassigned = true
    end
    reassigned
end
foo() # true

That issue, eg needing to declare global in the loop, only happens while working on the global scope.
That is avoided by putting your code inside functions.
Functions are also compiled once per set of concrete argument types they’re called with (although they may also get online into functions calling them).

This means that things like type inference only have to happen the first time a function is called (for the given set of concrete argument types), and that the compiler optimized them. Ie, putting all your work in functions should make your code fast, while avoiding this global for loop issue.
Behavior of loops inside functions didn’t change from 0.6.