Use of include outside and inside function

Hi there,

I have a file called file.txt, with the following contents:

N_questions = 4
ini_window = "2021-04-10 14:00"

I will use the variables N_questions and ini_window later on, in a (long) Julia script I named include_within_function.jl, which starts like:

using Dates

function build_df(file)
    include(file)

    if !(isinteger(N_questions) && N_questions > 0)
        error("N_questions must be a positive integer.")
    end

    dtformat = DateFormat("y-m-d H:M")
    ini_window = DateTime(ini_window, dtformat)
end

After declaring

file = "file.txt"
include("include_within_function.jl")

and then

build_df(file)

I get the error:

ERROR: UndefVarError: ini_window not defined

Sorry for the silly question, but: Why is it the variable N_questions is recognized (since the if loop issues no error), while the ini_window variable is not? I am almost sure it is a matter of scope, but am not able to figure it out! I say this because, when I run the statements of the body of the build_df function outside it, the variable ini_window is defined…
Could someone give me a nice detailed and pedagogical explanation for this behavior, with examples, if possible?
PS: On a parenthetical note, I would also appreciate suggestions as to the best way for Julia to digest parameters or variables provided in an ascii file instead of includeing it, as for the file.txt above.

Using include inside a function definition isn’t going to be useful since it evaluates the contents of the file in the current global scope rather than the functions local scope. See the first sentence of it’s docstring: “Evaluate the contents of the input source file in the global scope of the containing module.” As to why the first variable is visible and the second not, my guess would be that it’s just an artifact of how the eval is done inside include, don’t go relying on it.

I’d suggest using a “real” data format for your text file, probably TOML is the simplest to get working.

Inside config.toml

N_questions = 4
ini_window = "2021-04-10 14:00"

and then in do:

julia> import TOML

julia> function build_df(file)
           config = TOML.parsefile(file)

           if !(isinteger(config["N_questions"]) && config["N_questions"] > 0)
               error("N_questions must be a positive integer.")
           end

           dtformat = DateFormat("y-m-d H:M")
           ini_window = DateTime(config["ini_window"], dtformat)
       end

julia> build_df("config.toml")

Mixing include and global/local scopes together might seem to work nicely in little examples sometimes, but it’s just going to cause you pain more often than not. Just use a real data format, whether it’s TOML, or JSON or something else doesn’t matter too much.

3 Likes

I fell so proud of this ridiculous PR.

2 Likes

It’s the little details that matter the most.

1 Like