【问题标题】:Including a module and calling one of its functions from within another module in Julia包含一个模块并从 Julia 的另一个模块中调用它的一个函数
【发布时间】:2020-04-17 14:41:01
【问题描述】:

假设我有一个模块,Module1 定义了一个结构和一个 fit() 函数。我有另一个模块,称为 Parent,它包括 Module1 并定义了一个 test() 函数,该函数也调用 fit()。如果我从模块 1 定义结构,然后从 Parent 调用 test(),我会遇到命名空间问题。下面是这个例子的代码:

#this module would be in a separate file
module Module1
    struct StructMod1
    end
    export StructMod1
    function fit(s::StructMod1)
    end
    export fit
end

module Parent
    #including the module with include("Module1.jl")
    module Module1
        struct StructMod1
        end
        export StructMod1
        function fit(s::StructMod1)
        end
        export fit
    end
    #including the exports from the module
    using .Module1
    function test(s::StructMod1)
        fit(s)
        return s
    end
    export test
end

using .Parent, .Module1

s = Parent.Module1.StructMod1()
@show test(s)
s2 = StructMod1()
@show test(s2)

还有输出

test(s) = Main.Parent.Module1.StructMod1()
ERROR: LoadError: MethodError: no method matching test(::StructMod1)
Closest candidates are:
  test(::Main.Parent.Module1.StructMod1) 

或者,如果我将 using .Module1 替换为 using ..Module1,则 s2 的定义有效。但是,当使用 .Parent 调用时,我必须确保 Module1 已经加载。

用一个模块定义结构然后将其与另一个模块的函数一起使用的最佳方法是什么?

【问题讨论】:

    标签: struct module namespaces load julia


    【解决方案1】:

    双重包含导致错误。在您的示例中,Parent.Module1Module1 不同。将include 视为愚蠢的复制/粘贴很有用。即使它们共享相同的源文件,双重包含也会使它们显示为两个不同的模块(如您的示例所示)。

    解决办法是include只用一次,用relative imports引用模块。

    至于组织整套模块,我喜欢在主模块中依次include所有模块,然后在需要的地方使用相对导入。我发现这是最简单的方法。

    最终版本如下所示:

    # Module1.jl
    module Module1
        struct StructMod1
        end
        export StructMod1
        function fit(s::StructMod1)
        end
        export fit
    end
    
    # Parent.jl
    module Parent
        using ..Module1
        function test(s::StructMod1)
            fit(s)
            return s
        end
        export test
    end
    
    #Main.jl
    include("Module1.jl")
    include("Parent.jl")
    
    using .Parent, .Module1
    
    s = Parent.Module1.StructMod1()
    @show test(s)
    s2 = StructMod1()
    @show test(s2)
    

    【讨论】:

    • (或者,当然,另一种方式也是有效的,在Parent中定义Module1only,在Main中写using .Parent, .Parent.Module1。)两者都是合理的! :)
    猜你喜欢
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    • 2014-12-01
    • 2014-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多