Nesting a for loop in a while loop

Hi,

I apologize if this is a very elementary mistake but I still struggling with programming and Julia. I would like to iterate through a list while a certain conditions hold true. I would also like to be able to stop the process with an outside code at any time without resorting to the ctrl c method. I thought the most intuitive way to handle this task would be to nest a for loop in a while loop.

With a while loop I can do something like this

 function sqrt(x)
    repeat = Ref(true)
    count = 0
    @async while count< 5 && repeat[]
        println(" the square root of $x is $(x^(1/2)) ")
        count+=1
        sleep(5)
    end 
    return(repeat)
end  

If I input a = sqrt(4) I would get something like the following

julia> b=sqrt(4)
 the square root of 4 is 2.0 
Base.RefValue{Bool}(true)
julia>  the square root of 4 is 2.0 
julia>  the square root of 4 is 2.0 

Because of the “count” condition this would continue for 5 times or I could terminate the program at anytime by entering

julia> b[]=false
false

However once I turn x into a list and try to iterate through it with a for loop, (nest a for loop in a while loop) it appears that the while loop conditions no longer are being tested.

e.g.

function sqrt(sets)
    repeat = Ref(true)
    count = 0
    @async while count< 5 && repeat[]
        for i in sets
            try
                println("the square root of $i is $(i^(1/2))")
                count+=1
                sleep(5)
            catch
                continue
            end 
        end 
    end 
    return(repeat)
end 

I get something like this.

julia> a = sqrt([4,16,25,36,81,100])
the square root of 4 is 2.0
Base.RefValue{Bool}(true)
julia> the square root of 16 is 4.0
julia> the square root of 25 is 5.0
julia> the square root of 36 is 6.0
julia> a[]=false
false
julia> the square root of 81 is 9.0
the square root of 100 is 10.0

As you can see the “count” condition no longer limits the lines of output and I am no longer able to terminate the program with the reference call. Consequently I assume that the conditions of the while loop are being ignored because of the way I nested the for loop. If anyone has any insights on what is happening and the proper way to approach something like this in Julia it would be greatly appreciated. Thank you.

The code seems to work as expected to me, but this comment of yours

As you can see the “count” condition no longer limits the lines of output

makes me think that you are confused about what the code should be doing.

You have a while with a for inside, changing repeat (a outside of the function) guarantees that the while will not start the next iteration of itself but the while only do a single iteration, in which the for inside it does 5 iterations.

I believe what you wanted to do is:

julia> function sqrt(sets)
           repeat = Ref(true)
           count = 1
           @async while count < 5 && repeat[]
                   i = sets[count]
                   try
                       println("the square root of $i is $(i^(1/2))")
                       count+=1
                       sleep(5)
                   catch
                       continue
                   end 
           end 
           return(repeat)
       end
1 Like

The test of the condition on repeat is outside the for loop, so probably you need to add something like !repeat[] && break inside the for loop so it is sensible to that flag.

1 Like

Thank you! this really clears things up a lot. The code now gets stuck if it encounters an error. e.g. if sets = [4,16,-25,36,81] it just gets stuck at -25 as opposed to throwing an error at -25 and then continuing through the iteration. So I added a count+=1 after the catch statement. Is that the correct approach to address the issue?

julia> function sqrt(sets)
           repeat = Ref(true)
           count = 1
           @async while count < 5 && repeat[]
                   i = sets[count]
                   try
                       println("the square root of $i is $(i^(1/2))")
                       count+=1
                       sleep(5)
                   catch
                       count+=1 
                       continue
                   end 
           end 
           return(repeat)
       end

thanks! would this be done by putting an if then statement within the for loop?

!repeat[] && break

and

if !repeat[]
    break
end

are the same (&& is the circuit-breaking and operator, meaning that break will be evaluated only if the first condition holds).

I would go with:

julia> function sqrt(sets)
           repeat = Ref(true)
           count = 1
           @async while count < 5 && repeat[]
                   i = sets[count]
                   try
                       println("the square root of $i is $(i^(1/2))")
                   catch
                       println("error when tried to compute sqrt($i)")
                   finally
                       sleep(5)
                       count+=1 
                   end 
           end 
           return(repeat)
       end

Note that you cannot remove the catch and stay just with the finally, because otherwise the async thread will bubble the exception up.

2 Likes