Mysterious error: undefined variable


#1

Below is a simple program to integrate acceleration and velocity via Forward Euler. I received an error message (below) that vel is undefined; I can’t figure out what is causing this. The program is OK if I initialize all the scalars inside the open...do.. block. I assume that the problem is caused by some subtle interaction of scoping rules, but it would be great if someone could spell it out.

module pushsq_direct

const load_table = [
0.00E+00		-2.041201359
5.00E-07		-1.661441147
1.00E-06		-0.311829107]

h = .02
w = .02
d = 1.
density = 1180.
totalmass = density / (h*w*d)
vel = 0.
pos = 0.
open("pushsq_direct.out", "w") do hnd
    for tind = 2 : size(load_table,1)
        deltat = load_table[tind,1] - load_table[tind-1,1]
        pressure = load_table[tind,2]*1e6
        force = pressure * h * d
        acc = force / totalmass
        vel += acc * deltat
        pos += vel * deltat
        println(hnd, "t = ", load_table[tind,1], " vel = ", vel, " pos = ", pos)
    end
end

end

Error message (Julia 0.6.1, Windows 10)

julia> include("pushsq_direct_mini.jl")
ERROR: LoadError: UndefVarError: vel not defined
Stacktrace:
 [1] (::pushsq_direct.##1#2)(::IOStream) at C:\Users\vavasis\ownCloud\Documents\Katerina\cohesive\conic_jl\pushsq_direct_mini.jl:21
 [2] open(::pushsq_direct.##1#2, ::String, ::String) at .\iostream.jl:152
 [3] include_from_node1(::String) at .\loading.jl:576
 [4] include(::String) at .\sysimg.jl:14
while loading C:\Users\vavasis\ownCloud\Documents\Katerina\cohesive\conic_jl\pushsq_direct_mini.jl, in expression starting on line 15

#2

A do-block creates a Hard Local Scope which inherits all variables from the parent scope (here the global) if the variables are not modified.

In your example you could add the line global pos, vel inside the do-block to force vel and pos to be inherited and achieve the expected behaviour.

open("pushsq_direct.out", "w") do hnd
    global pos, vel
    for tind = 2 : size(load_table,1)
        ...

The for-loop creates a soft local scope and thus permits modifying the parent’s (do block) variables.


#3

Thanks! I didn’t know this, but it is in the manual in the section on Variable Scopes. It isn’t in the section on do blocks, I just submitted a PR to add a sentence to the latter section. Meanwhile, I discovered another bug in my code: it should be mass = density * volume!


#4

Further follow-up on my own post-- apparently the notions of hard and soft local scope are undergoing significant revision; see

https://github.com/JuliaLang/julia/pull/19324#pullrequestreview-8520079

And in fact, my posted code runs without error in the most recent 0.7 nightly.