Julia 1.0 のmoduleを使うとき、moduleの中にmoduleをいれたいこともあるだろう。
twitterでこのような話が出ていたので、自分なりの解決方法を示す。
#Julia言語 【moduleのnestの仕方】私も知らないのでみんなに質問。
— 黒木玄 Gen Kuroki (@genkuroki) September 27, 2018
module A
f(x) = 2x
module B
import ..A: f
g(x) = f(f(x))
end
end
import .A
A.B.g(π)
→12.566370614359172
のような感じにするのが普通なのでしょうか?
スクショとGist URL紹介に続くhttps://t.co/nErF6ROqSV
解決したいもの
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 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 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 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も呼び出せるようになっている。