I am writing a simulation code where there is an “input.toml” file which contains the initialization parameters (20 to 30 parameters) for the simulation. It works fine if I keep the code in the main where the variables stay global. I tried to wrap it in a function for sake of organizing and readability:
using TOML
function parser()
println("PARSING input parameters from 'input.toml' file")
input_parameters = TOML.parsefile("input.toml")
println()
blob_width = input_parameters["Initial parameters"]["blob_width"]
end
parser()
println("blob_width = $(blob_width)")
my input.toml file looks like this:
["Initial parameters"]
blob_width = 2.0
and i get the following error
ERROR: LoadError: UndefVarError: `input_parameters` not defined in `Main`
What is the Julia way to do this correctly for organizing & readability?
Use function arguments to pass things into the function (e.g. the name of the TOML file), and use function return values (or less commonly mutate the arguments) to pass information out of the function. Don’t use global variables, in general.
This is not really about Julia per se. It’s basic to the concept of a “function” in any programming language, and being reluctant to use global variables is standard software-engineering practice.
The error means exactly what it says — you never defined this variable. Presumably you meant to call input_parameters = TOML.parsefile("somefile.toml")
Note that none of the confusion here is really specific to parsing, so I’ve edited the post title.
Okay. I tried to do what you suggested, but I think I am doing something wrong, I am still facing the same error
ERROR: LoadError: UndefVarError: blob_width not defined in Main
using TOML
input_parameters = TOML.parsefile("input.toml")
function parser(dictionary)
println("PARSING input parameters from the dictionary")
blob_width = dictionary["Initial parameters"]["blob_width"]
return blob_width
end
parser(input_parameters)
println(blob_width)
What am I doing wrong?
The objective is to use the parsed parameters throughout the code in various functions. Doesn’t that justify Global variables?
Another concern I have is that it becomes messy to return 30 parameters. Is there a better way?
You need blob_width = parser(input_parameters) in order to assign the return value to a variable.
I would recommend reading some tutorial material on the “function” concept in programming, such as this chapter from Think Julia. (Or similar material from any programming language; this is not specific to Julia.)
If a function returns 2 to 10 parameters you can return a tuple:
julia> function test()
a=1
b=2
c=3
return a,b,c
end
test (generic function with 1 method)
julia> a, b, c = test()
(1, 2, 3)
julia> a
1
julia> b
2
julia> c
3
Personally, I would let the parser function return all interesting input parameters in a NamedTuple, e.g.:
using TOML
function parser(filename)
println("PARSING input parameters from '$filename' file")
input_parameters = TOML.parsefile(filename)
println()
(; blob_width = input_parameters["Initial parameters"]["blob_width"],
blob_height = input_parameters["Initial parameters"]["blob_height"])
end
iparams = parser("input.toml")
println("blob_width = $(iparams.blob_width)")
println("blob_height = $(iparams.blob_height)")
So that all input parameters are collected in one variable (iparams in this case). If you really want to have each input variable in its own variable, this can still be done (using the same parser function as above):