How to write a program as a Julia package?

RE:

That’s because you shouldn’t run include() from within a function (much in the same way you shouldn’t run import/using from within a function).

Doing so appears to run include() in the calling scope… and so you start getting strange behaviours. I am almost certain running include() from within a function is bad practice, and I would personally avoid it. include() isn’t exactly the same as #include in C/C++.

A small tweak to your methodology

What you should instead be doing is something more like:

include("ReadTables.jl")
include("BuildTables.jl")
include("WriteTables.jl")
include("PlotTables.jl")

function process(options)
    read_input_tables(options) # defined in ReadTables.jl
    build_more_tables(options) # defined in BuildTables.jl
    write_some_tables(options) # defined in WriteTables.jl
    plot_important_tables(options) # defined in PlotTables.jl
    return results #written somewhere in the module's global namespace, I suppose
end

This coding shift requires encapsulating much of the code you wrote in the global namespace (of *Tables.jl files) inside these read_input_tables()/build_more_tables()/… functions. You can leave the code in their respective files - just wrap them inside one-or-more function call(s).

If you want to keep the data around inside the global namespace: just remember to declare/tag the variable as global:

function readtable(...) #This low-level function is fine as it is. No need to change it.

function read_input_tables(options)  #New encapsulating function
    #...
    global tableY = readtable(options.inputfilepath, "Table Y-1")
    #...
end

:warning: No scripting inside modules.

One of the consequences of what @mkitti mentioned:

is that you shouldn’t write your *Tables.jl files as conventional scripts with code running in the global namespace (ie: “global” = not “inside” functions).

That only works for executing files in the REPL. As soon as you wrap files into modules, your non-static, “execution-mode” code should all be written inside one (or-more) functions.

I don’t think this is explicitly stated anywhere (I’m sort of sad to make this realization just now)… but it is a natural consequence of what @mkitti just said.

Only “static” code that can effectively be pre-compiled is allowed to exist outside functions.

:smile: A more Julia-friendly solution

I have a few more relatively important suggestions for improving your code, but this particular issue seems to be your dominant problem - so I’ll refrain from giving you more confusing tips.

The JuilaScripting.jl sample I provided earlier shows a more Julian way to write your module (I modelled it closely after your ASME_Materials.jl module to help you better understand the Matlab->Julia transition)

:eyeglasses: take another look!: GitHub - ma-laforge/JuliaScripting.jl

I also tried to add useful comments to the global namespace & __init__() functions so you can get a better idea of what should go where.

1 Like