Use an external variable inside a loop

Hello, i need help to use an external variable inside a loop. I’ve been trying for days and i still don’t have an idea of how to use something outside a for inside it, change it and then use it’s new value outside. Here’s an example of what i want to do. Please, help ASAP 7w7
NOTE: I’ve already marked the places where the variables are.


global r = []

while true
a = readline()
	if typeof(tryparse(Int, a))==Int64
		parse(Int, a)
		push!(r, a)
	end
	typeof(tryparse(Int, a))!=Int64 && break
end
b = length(r)

global ans = 0			#!
for i=1:b
	ans = ans + r[i]	#!
end

println(ans)			#!
println()

Short answer: You need to use global inside the loop to tell Julia that the variable in the loop is the global one. Using global outside of the loop is not an error, but it doesn’t do anything.

Longer answer: This has been discussed literally to death since the release of Julia 1.0, and you can find lots of other discussions about this issue on the forum. The easiest way to avoid the issue entirely is to write functions rather than working at global scope:

function my_function(r)
  b = length(r)
  ans = 0
  for i in 1:b 
    ans = ans + r[i] 
  end
  println(ans)
end

A further benefit of using functions instead of globals is that it will make your code dramatically faster.

For some further good news, Julia 1.5 adjusts the behavior of the Julia REPL so that your exact example will just work. It should be coming out pretty soon (it’s currently in beta).

9 Likes

It will also just work (even in the current version of Julia) if you run interactive code from within a Jupyter notebook via IJulia.

6 Likes

In addition to what’s already been said, if performance is a concern, you’ll want to avoid using globals directly because they are not type stable. You can fix this by using const and Ref. (const works for the array because you’re changing the values within the array, not the array itself, but still has the downside that you can’t redefine the variable name.

Your example made type-stable:

const r = Vector{Int}()

for x in 1:10
 push!(r, x)
end

const ans = Ref(0)                    #!
for i=1:length(r)
 ans.x += r[i]  #!
end

println(ans.x)                  #!
println()
4 Likes

Hey, I can say that what you have written really works, since I tried it on the JULIA console and it definitely worked. Even so, when I run it as a program, it gives me an error that dictates that the function name is unknown. Do you know how I can solve that? Will my syntax be wrong?
NOTE: Thanks for answering so fast. I’m starting to use Julia as my main programming language, i really love how simple it is.

2
3
4
5
ERROR: LoadError: UndefVarError: SUM not defined
Stacktrace:
[1] top-level scope at C:\LOCATION\NAME.jl:13
[2] include(::Module, ::String) at .\Base.jl:377
[3] exec_options(::Base.JLOptions) at .\client.jl:288
[4] _start() at .\client.jl:484
in expression starting at C:\LOCATION\NAME.jl:13   

Can you post the code, or at least the area around where the error occurred? Looks like it’s in NAME.jl, line 13.

1 Like
#MAIN STREAM
global r = []
#-
while true
	a = readline()
	if typeof(tryparse(Int, a))==Int64
		parse(Int, a)
		push!(r, a)
	end
	typeof(tryparse(Int, a))!=Int64 && break
end
#-
h = SUM(r)
#-
println(h)
println()


#FUNCTION STREAM
function SUM(r)
	ans = 0
		for i in 1:length(r) 
			ans += r[i]
		end
	return(ans)
end

Isn’t the problem here just that you call your SUM function before you define it?

Beside the point: you could of course just use the built-in sum function rather than defining your own. If you define your own, note that arrays in Julia are iterable, so you can just do

for i in r
    ans += i
end

to iterate directly over the elements in r

3 Likes

That would be good to go from element to element inside the array, but what I’m trying to get is the sum of all the elements and save the result in a single variable. That’s the purpose of ans inside the function.
I was able to do it in C# and using the same method, it just doesn’t works here.

You should try @nilshg’s answer before saying that, it does exactly the same thing as your code (you can literally just replace your for loop for his). (I’m not sure I understand your answer though but it looks like you didn’t understand his)

1 Like

I agree with Thibaut - your problem here isn’t related to how you specify your iteration, but the order in which you execute the code. As a quick sketch, what you need is:

# first define your own SUM function
function SUM(r)
...
end

# then initialize and accumulator
# Note: it helps performance to specify the type of the elements
# that you'll put into your array if you know it in advance
r = Int[]

# then your loop
while true
...
end

# now you can sum and print
h = SUM(r)
@show h

I appreciate that Julia’s error messages and stack tracers can seem daunting to newcomers, but this one is actually pretty clear I would say: it tells you SUM not defined, that is Julia doesn’t know the SUM function. And that’s because in the code you posted, #FUNCTION STREAM comes after you called SUM(r), so when your code gets to the line where SUM(r) is called, SUM doesn’t actually exist yet.

2 Likes

Hey, i found a solution the the problem that i was having. Apparently it had something to do with the type of elements that the array contained. I learned that first you need to specify it before trying to do anything with it. Here’s how the solution that i found looks, using sum!([dims], array) and specifying the type of elements that the array contains basically by force XD:
NOTE: I use this method because i tried every way of just putting a variable inside a loop and it just didn’t worked at all. That means that this is a solution for this exact problem. From my perspective there are a lot of solutions in this language to it’s own limitations, which means that if you get to see this forum looking for an answer and just don’t find it, keep investigating and searching for it, you’ll eventually get a solution :slight_smile:.

r = [0]

while true
	a = readline()
	if typeof(tryparse(Int, a))==Int64
		if r[1] == 0
			pop!(r)
		end
		push!(r, parse(Int, a))
	end
	typeof(tryparse(Int, a))!=Int64 && break
end

k = sum!([1], r)

println(k[1])
println()

Note how i used the zero as the first element of the array to remark the kind of elements that it contains without using the whole array declaration expression.

THANKS TO EVERYONE WHO TRIED TO HELP ME! U GUYS ARE THE BEST :tada: :laughing: