X not defined error, even though it is?


#1

Hi,

I have this code:

using Pkg;

n = 1.0;

function yfc(t)
    # x in here is actually t from before
    cos(1/3 * t^3 + n*t)
end;

const t0 = 0;
const tf = 1000;
const N = 10000000;
const dt = 1000 / N;
t = t0:dt:tf;
const x = 0.0 ;

for i in 1:N;
    k1 = dt * yfc(t[i]);
    k2 = dt * yfc(t[i] + 1/2*dt);
    k4 = dt * yfc(t[i+1]);
    x = x + 1.0/6.0 * k1 + 2.0/3.0 * k2 + 1.0/6.0 * k4 ;
end

and I’m getting the error:

ERROR: LoadError: UndefVarError: x not defined
Stacktrace:
 [1] top-level scope at /data/GitHub/mine/math/julia-scripts/airy-ai-approx.jl:24 [inlined]
 [2] top-level scope at ./none:0
 [3] include(::String) at ./client.jl:403
 [4] top-level scope at none:0
in expression starting at /data/GitHub/mine/math/julia-scripts/airy-ai-approx.jl:20

which confuses me. x is defined, originally as a constant and then as a variable that is updated over the loop. What is the problem here?


#2

I believe that the notorious global scope issue is at play here, but, more importantly, const means constant, so if you declare something const, you should not attempt to assign it.


#3

Yep, but if I remove the const before x I get the same error. Adding const was my attempt to fix this original issue.


#4

Looking at the linked post I thought maybe adding an if conditional for i=1 would fix it, like changing the for loop to:

for i in 1:N;
    k1 = dt * yfc(t[i]);
    k2 = dt * yfc(t[i] + 1/2*dt);
    k4 = dt * yfc(t[i+1]);
    if i == 1
        x = 0;
    end
    x = x + 1.0/6.0 * k1 + 2.0/3.0 * k2 + 1.0/6.0 * k4 ;
end

and removing the above (before the loop) x = 0.0; declaration would fix it, but nope same x undefined error.


#5

Again, this is the global scope issue, see my link above. I think the summary is that this behavior will change in a future version of Julia, as you can see it has been discussed ad nauseum.

In the meantime, this really isn’t something you would want in global scope anyway. You should put such code in functions, and if the functions ever do need to reference global variables, those should be declared const.


#6

x is found to be undefined, because you are trying to use it in a for loop (local scope) inside the global scope. This local scopes don’t (with some exceptions) inherit variables from the global scope unless it is explicitly stated with the global keyword.

For your understanding I advise you to read the documentations
part about scope of variables.

Try this:

n = 1.0

function yfc(t)
    # x in here is actually t from before
    cos(1/3 * t^3 + n*t)
end

const t0 = 0
const tf = 1000
const N = 10000000
const dt = 1000 / N
t = t0:dt:tf
x = 0.0 

for i in 1:N
    global x
    k1 = dt * yfc(t[i])
    k2 = dt * yfc(t[i] + 1/2*dt)
    k4 = dt * yfc(t[i+1])
    x = x + 1.0/6.0 * k1 + 2.0/3.0 * k2 + 1.0/6.0 * k4 
end

julia> x
0.6663639957011587

But you should really think about putting the code in a function if you want it to run perfomantly.

PS: There is no need to put a semicolon behind every statement. This is only useful to suppress the output of things entered in the REPL.