bitWise
bitWise

Reputation: 709

Problem with declaring and changing the value of a variable in julia

What is wrong with my code? Do I have to declare x before using it?

function f(n::Int64, t::Int64)
A = ones(n,n)
for i=0:t
    if i > 0
        A[x,a] = rand()*A[x,a] + rand()
    end
    y = rand(1:n)
    b = rand(1:n)
    if i > 0
        A[x,a] = rand()*A[x,a] + rand()*A[y,b]
    end
    x = y
    a = min(b, rand(1:n))
end
return A
end

Here is the error thrown when trying to call f:

UndefVarError: x not defined

Upvotes: 1

Views: 754

Answers (1)

Bogumił Kamiński
Bogumił Kamiński

Reputation: 69819

I think that the reason is more complex, as similar code in Python would work.

For example compare (Python):

>>> def f():
...     for i in range(3):
...         if i > 0:
...             print(a)
...         a = i
...
>>> f()
0
1

to (Julia):

julia> function f()
           for i in 0:2
               if i > 0
                   println(a)
               end
               a = i
           end
       end
f (generic function with 1 method)

julia> f()
ERROR: UndefVarError: a not defined

So what is the difference? As the Julia manual explains here you have:

for loops, while loops, and comprehensions have the following behavior: any new variables introduced in their body scopes are freshly allocated for each loop iteration, as if the loop body were surrounded by a let block

This means that in your code variables a and x as they are local to the for loop are freshly allocated in each iteration of the loop. Because of this the variable has to be assigned to before it is accessed inside the loop.

Therefore it is not needed to assign a value to x and a before the loop. It is enough to define them in scope outer to the loop (even without assigning of the value). For example like this:

julia> function f(n::Int64, t::Int64)
           A = ones(n,n)
           local x, a
           for i=0:t
               if i > 0
                   A[x,a] = rand()*A[x,a] + rand()
               end
               y = rand(1:n)
               b = rand(1:n)
               if i > 0
                   A[x,a] = rand()*A[x,a] + rand()*A[y,b]
               end
               x = y
               a = min(b, rand(1:n))
           end
           return A
       end
f (generic function with 1 method)

julia> f(1,1)
1×1 Array{Float64,2}:
 0.94526289614139

Now it works because x and a are not freshly allocated in each iteration of the loop.

In my original toy example it would look like:

julia> function f()
           local a
           for i in 0:2
               if i > 0
                   println(a)
               end
               a = i
           end
       end
f (generic function with 2 methods)

julia> f()
0
1

and you see that you get exactly what you had in Python.

Upvotes: 2

Related Questions