Issue with Wildcard Import in Julia Module

I’m encountering an issue with wildcard imports (“import .ModuleName: *”) in Julia. Specifically, when attempting to import all symbols from a module using the wildcard syntax, the symbols do not seem to be available in the importing file.

Here’s an example:

Module definition:

# Module file: ModuleA.jl
module ModuleA
export *

function functionA(arg1::AbstractString, arg2::AbstractString)
    # Function A implementation
end

function functionB(arg1::AbstractString, arg2::AbstractString)
    # Function B implementation
end

end

Main file:

# Main file: main.jl
include("ModuleA.jl")
import .ModuleA: *

functionA("arg1", "arg2")  # Error: functionA not defined

When I attempt to import all symbols from the “ModuleA” module using “import .ModuleA: *”, the “functionA” function is not recognized in the main file, resulting in an error. However, when I specifically import the “functionA” function using “import .ModuleA: functionA”, it works as expected.

I want to use the wildcard import to keep the code more readable and avoid listing individual functions. What could be causing this issue?

I use Juliav1.6 in VS-Code.

Any help or insights would be greatly appreciated. Thank you!

You are exporting the symbol * — this is not a wildcard, this is the name of the multiplication function.

Julia doesn’t have “wildcard” (globbing/pattern-matching) export and import, unlike Python.

Do export functionA, functionB explicitly in the module. To use all of the exported symbols of a module, do using .ModuleA

(Somebody did make a package ExportAll.jl to export everything from a module, but I don’t think it’s widely used.)

7 Likes

As stevengj said, you exported the multiplication function. I tried this which seems to work:

module Foo
    foo1() = "this is foo1"
    foo2() = "here is foo2"
    function get_func_strings()
        symbols = names(Foo, all=true) # this contains a lot of unecessary stuff
        n = length(symbols)
        symbols = symbols[(n÷2 + 1):end] # first elements aren't useful
        filter!(smb->smb ∉ [:eval, :include, :Foo], symbols) # we don't want to reexport eval, include and the module name, although this one will be exported nonetheless
        return map(String, symbols)
    end
    for fname in get_func_strings()
        "export $fname" |> (eval ∘ Meta.parse)
    end
end
1 Like

You may want to consider loading a module via using rather than include.

https://docs.julialang.org/en/v1/manual/code-loading/

When you are new, the simplest way might be manipulating LOAD_PATH as follows.

# Main file: main.jl
push!(LOAD_PATH, @__DIR__)
using ModuleA: functionA

functionA("arg1", "arg2") 

I do not recommend manipulating LOAD_PATH in the long term.

1 Like

Thank you all for your responses! That helped clearing up the confusion.

1 Like