LoginSignup
15
11

More than 5 years have passed since last update.

Juliaのmodule自由自在

Posted at

Julia 1.0 のmoduleを使うとき、moduleの中にmoduleをいれたいこともあるだろう。
twitterでこのような話が出ていたので、自分なりの解決方法を示す。


解決したいもの

module.jl
module Level1
    function fire()
        println("fire")
    end
    module Level2
        function firestorm()
            println("storm")
            fire()
        end
        module Level3
            function dragonfire()
                println("dragon")
                firestorm()
                fire()
                println("(^_^)v")
            end
        end
    end
end

using .Level1
Level1.Level2.firestorm()

をエラーなく動かしてみたい。上のコードは、

storm
ERROR: LoadError: UndefVarError: fire not defined

とエラーが出る。stormまでは出力されているので、firestorm()の呼び出しはうまくいっている。

なお、

module.jl
module Level1
    function fire()
        println("fire")
    end
    module Level2
        function firestorm()
            println("storm")
            Level1.fire()
        end
        module Level3
            function dragonfire()
                println("dragon")
                firestorm()
                fire()
                println("(^_^)v")
            end
        end
    end
end

としても、同様のエラーが出る。

Juliaでのmoduleの呼び出しについて

Juliaで自前のmoduleを呼び出すときは、ドット.をつけて.Level1のように呼び出す。
これは、Linuxで言うところの「現在位置./」のようなものと考えればよい。つまり、現在位置「./」にあるLevel1というmoduleを呼び出している。
もし、Level2モジュール内のfirestorm()からLevel1モジュールのfire()を呼び出したいのであれば、「現在位置より一つ上の階層のディレクトリ../」と同じように、..をつければよい。つまり、

module.jl
module Level1
    function fire()
        println("fire")
    end
    module Level2
        using ..Level1
        function firestorm()
            println("storm")
            Level1.fire()
        end
        module Level3
            using ...Level1
            using ..Level2
            function dragonfire()
                println("dragon")
                Level2.firestorm()
                Level1.fire()
                println("(^_^)v")
            end
        end
    end
end

using .Level1
Level1.Level2.firestorm()
Level1.Level2.Level3.dragonfire()

ならfirestorm()はエラーなく呼び出せる。なお、さらに上の階層は...とすればよいので、上のコードでは、Level3からLevel1のfire()を呼び出すことができる。

上のコードは少し煩雑な気もするので、整理することとする。exportをつけたfunctionはいちいちモジュール名をつけなくてよくなるので

module.jl
module Level1
    export fire,Level2
    function fire()
        println("fire")
    end
    module Level2
        using ..Level1
        export firestorm,Level3
        function firestorm()
            println("storm")
            fire()
        end
        module Level3
            using ...Level1
            using ..Level2
            export dragonfire
            function dragonfire()
                println("dragon")
                firestorm()
                fire()
                println("(^_^)v")
            end
        end
    end
end

using .Level1
using .Level2
using .Level3
firestorm()
dragonfire()

と書くことができる。
Level1モジュールのexportにfire()があるのでfireはLevel1と書く必要がなく、Level2もあるので、usingをする際に.Level1.Level2と書く必要がない。また、Level2のexportにfirestormがあるのでLevel2を書く必要がないために、firestormをそのまま呼び出すことができるようになっている。同様に、dragonfireも呼び出せるようになっている。

15
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
11