Hi everyone.
This might be a REALLY silly question, but I wonder if it is possible.
I am making this function Set_Up(). It is design to load all other functions in my code, force precompilation, load global variables, etc.
Because sometimes something goes wrong I have:
try
Do a lot of things
catch e
printstyled(" An error ocurred.",color=:red)
printstyled("Please run Set_Up() again.",color=:red)
sleep(1)
end
I wonder if inside the catch I can tell the function to run itself again. Something like:
try
Do a lot of things
catch e
printstyled(" An error ocurred.",color=:red)
printstyled("Set_Up() will run again after 1 second.",color=:red)
sleep(1)
Set_Up()
end
Yes. I actually implemented this for a network handshaking function a few years ago. I did also have a “retries” variable that increments on each restart, with provision to exit if too many retries. This kept the function from being stuck too long (in practice the restart hardly ever happened, without there being a network glitch).
This is called recursion, an important technique in computer science. Note that each call allocates on the stack, so if you go too deep you will get a stack overflow (which gave its name to a famous website).
julia> counter = 0;
julia> function f()
global counter += 1
f()
end;
julia> f()
ERROR: StackOverflowError:
Stacktrace:
[1] f()
@ Main ./REPL[12]:2
[2] f() (repeats 79980 times)
@ Main ./REPL[12]:3
julia> counter
130830
So f was able to call itself recursively 130830 times before the stack grew too big.
Hmm Hi guys.
I tried this… but my code just gets into a loop and never actually finishes… Not sure why.
I wonder if there is a line to kill the current execution and then call the function again.
What goes wrong is that some libraries in the OS need to be called twice (GMT package) for them to work. This is a problem of the package … and I can’t fix it hehehe.
With recursion, at some point you have to return anything which is not the function call to ensure that the recursion terminates. You do this via a conditional like “if counter > 100” and return nothing for that case.
For some kind of repeated call, you can also use retry (from HTTP if I’m not mistaken)
function myrecursion(depth::Int,arg)
if depth>=2
return nothing
else
println(arg)
@info("myrecursion was called (depth=$(depth))")
return myrecursion(depth+1,arg)
end
end
myrecursion(0,"foo")
0
I’m late to the party, but I want to point out that AFAIK the better practice would be to use a loop as opposed to recursion. Something like:
function Try_Set_Up()
try
# Do setup stuff
catch e
# Report error
return false
end
return true
end
function Set_Up_Keep_Trying()
setupsuccess = false
while !setupsuccess
setupsuccess = Try_Set_Up()
if !setupsuccess
sleep(1)
end
end
end
Or if you wanna be slick:
function Set_Up_Keep_Trying()
while true
Try_Set_Up() ? break : sleep(1)
end
end
To limit the number of iterations:
function Set_Up_Keep_Trying(; attempts=10)
setupsuccess = false
for i in 1:attempts
if Try_Set_Up()
setupsuccess = true
break
else
sleep(1)
end
end
setupsuccess || println("Setup failed after $attempts attempts")
end