x = 0
y = 0
er = false # or true for another branch
try
if er
x = 1
error()
else
x = 2
end
catch
x *= 10
finally
# x *= 100 ### this line would produce an error:
#### x from try/catch ist not available in finally
y = 300
end
println("x=",x, " y=", y)
For thist last thing, I could somehow circumwent it by using let block:
let
x = 0
y = 0
er = true # or false for another branch
try
if er
x = 1
error()
else
x = 2
end
catch
x *= 10
finally
x *= 100
y = 300
end
println("x=",x, " y=", y)
end
println("x=",x, " y=", y)
x=1000 y=300 x=0 y=0
Any idea how to pass the results to the outer scope?
In the first code, those xs and ys inside try catch blocks are all local variables. So global keyword must be prepended to them:
try
if er
global x = 1
error()
else
global x = 2
end
catch
global x *= 10
finally
# x *= 100 ### this line would produce an error:
#### x from try/catch ist not available in finally
global y = 300
end
Do I understand you correctly that in this case x and y are “really global”, i.e. avaliable across all files? If yes, I would give the variables some long obscure name and live with it, but actually it would be nice to have them available in the outer scope of the try block (i.e. in this module/function etc.) only. Could that be done, or is it currently a limitation of the language?
The scope of global variables are limited to the immediate module they belong to.
module OuterModule
x = 1
module InnerModule
x = 2
function f()
global x
println(x) # will print 2
end
end
function f()
global x
println(x) # will print 1
end
end
Incidentally, please note that the concept of “soft” and “hard” global scope is now obsolete, there is no such distinction in Julia 1.0. The manual you are using is outdated, use the link by @Sijun.
Generally, Julia underwent a lot of changes before 0.7/1.0, and a lot of material on the web is outdated.
@Tamas_Papp Reading discussions like this was definitely confusing (as confusing as the Julia scoping rules can be) AND helpful for me.
Loops and try-catch creating a local scope may have reasons (with try-catch-finally creating 3 separated scopes being expecially piquant). However normally you would want to pass the results to the “outer world”.
For myself, I’d sum up the following rules to avoid scoping problems:
global is evil. Especially never call loop or try-catch constructs on the global (script) scope
Put everything into functions as early as possible
Otherwise at least put loop or try-catch into a let block
Initialize the variable to be used to return results before the loop or try-catch construct. If the variable starting value is not used in the loop, initialize it with nothing
Like the following
let
k = nothing
for i in 1:2
k = i
end
@show k
end
function f2()
p = 0
for j in 1:4
p += j
end
return p
end
@show f2()
function tryit(sq)
ll = mm = nothing
try
mm = 9
ll = sqrt(sq)
catch
ll = sqrt(mm)
finally
ll += mm
end
return ll
end
@show tryit(10.0)
@show tryit("ten")
As for surprises: The following code works, and I am surprised. The variable soln was not declared anywhere outside of the loop and to my understanding it shouldn’t be available after the loop - still it is available: I then use it as the returned value from the function integrate_ode .
As for the code itself: it resulted from a port of an old Python project to Julia, mainly as an excercise. I measure the execution time at the iteration # 7 to compare with Python / scipy code. BTW it is about 10 times faster (with the potential to reduce the execution time by about a second as compared with Python )
function integrate_ode(y0, x_arr, m_l_arr, p_arr, ps_arr, signum, mdl_perm_coeff, ppw_opp, iteration)
loops = 1
if signum < 0
x_arr = reverse(x_arr)
else
if iteration == 7
loops = 1000
end
end
params = (x_arr, m_l_arr, p_arr, ps_arr, signum, mdl_perm_coeff, ppw_opp)
xspan = (x_arr[1], x_arr[end])
if loops > 1
eltime = @elapsed begin
for cnt in 1:loops
problm = ODEProblem(own_tmq_m_w, y0, xspan, params)
soln = solve(problm,reltol=1e-6,saveat=x_arr)
end
# about 3 to 4 ms per loop
end
@show eltime
else
problm = ODEProblem(own_tmq_m_w, y0, xspan, params)
# @show y0
soln = solve(problm,reltol=1e-6,saveat=x_arr)
end
if signum < 0
return reverse(soln(x_arr).u)
else
return soln(x_arr).u
end
end
module Outer
x = 1
module Inner
import ..Outer
x = 2
f() = println(x)
g() = println(Outer.x)
end
f() = println(x)
g() = println(Inner.x)
end
Outer.f() # 1
Outer.g() # 2
Outer.Inner.f() # 2
Outer.Inner.g() # 1
x defined in module Outer is not accessible to module Inner by the name x alone. x must be qualified by Outer (as Outer.x) and vise versa.
Unless qualified by appropriate module name, a variable defined in one module is not visible to other modules and (I think) can be said to be limited only to its immediate module it belongs to (so no name clash can occur).