Met a weird error; UndefVarError

Hi, I’m now writing my codes and encountered a really strange error:

As can be seen, the error said “obj_path_tmp not defined”.
However, in debugging mode (using Debugger), I can read the value (even add to obj_linearised):

So, what’s wrong with it? It’s really confusing …

EDIT: Is there any function to check if a variable is not defined previously?

P.S. Sorry for the images. I don’t know how to paste the result from REPL.

Please don’t post screenshots (copy should work from most IDEs and the terminal), and make an MWE.

1 Like

The debugger handles scope slightly wrong when you execute julia code in it, so if you defined obj_path_tmp in a more inner scope it is possible the debugger is showing it still being defined while it is not. Here is a MWE:

1|debug> st
In f() at REPL[11]:1
 1  function f()
 2      for i in 1:5
 3          a = 3
 4      end
>5      print(a)
 6  end

About to run: (print)(Main.a)
1|julia> a

1|debug> n
ERROR: UndefVarError: a not defined

One of the solutions is to put local obj_path_tmp in the same scope as you want to use it:

julia> function f()
           local a
           for i in 1:5
               a = 3
f (generic function with 1 method)

julia> f()

@kristoffer.carlsson Thank you. Your solution works very well!
Additional questions:

  1. As you answered, adding local a works well. However, it looks unnatural to write codes to me. Is there any other elegant solutions?
  2. I used to code with Python, and to debug codes, I usually added a short line like
    import ipdb; ipdb.set_trace(). Is there any counterpart in Julia like this? In my opinion, using Debugger sometimes bothers me; I have to use a macro @enter in front of a function.

I may ask some stupid questions because I’m new to Julia :slight_smile: Thanks again!

EDIT: your answer is probably related to here, and it seems in my case that obj_path_tmp was declared only in inner for loop, and therefore Debugger indicated that obj_path_tmp has not been defined “outside the inner for loop”. Am I right? (So confusing :frowning: )

Well, this is just the way Julia scoping rule works. If you need access to a variable that you declare in an inner scope, outside that scope you need to lift it to the outer scope using e.g. local. You could also just declare it like obj_path_temp = 0.0 or something like that instead of local if you are accumulating into it.

You can add @bp in your code and then run the code with @run. The debugger will stop at the @bp.

julia> function g()
           for i in 1:3

julia> f(i) = (@bp; println("hello $i"));

julia> @run g()
Hit breakpoint:
In f(i) at REPL[22]:1
>1  f(i) = (@bp; println("hello $i"))

About to run: (string)("hello ", 1)
1|debug> c
hello 1
Hit breakpoint:
In f(i) at REPL[22]:1
>1  f(i) = (@bp; println("hello $i"))

About to run: (string)("hello ", 2)
hello 2
Hit breakpoint:
In f(i) at REPL[22]:1
>1  f(i) = (@bp; println("hello $i"))

About to run: (string)("hello ", 3)
hello 3
1 Like

Thank you.
How Julia works is quite different from Python.
Actually, REPL is also an inconvenient part of Julia to me cuz I used to edit and run codes via vim and terminal. Probably I have to get used to Julia’s grammar and convention :frowning:
I really hope that it’s not familiar for a while, and give me both fast code development and high performance.

Anyway, thanks for your kind explanation :slight_smile: