俺のための Julia 入門(5)モジュール

モジュールとパッケージ作成

Julia
俺のためのJulia入門
Author

司馬 博文

Published

9/10/2020

概要
Julia は 2012 年に公開された科学計算向きの動的型付け言語である.

1 Module

1.1 導入

Module は,Julia において名前空間を提供する.

documentation における Base.map などである.現在 Module 内では大域的な名前を,外部から参照不可能にする方法はない. 現在の Module は @__MODULE__ マクロで確認できる.

println(@__MODULE__)
Main

この時の ”method” の語は,OOP に似ている使い方であるが,やはり多重ディスパッチが意識されている.Julia の多重ディスパッチにおいて,関数とは method の張り合わせである.

1.2 module文とexport文:Module 定義

module MyModule

export my_function

const global_var = 42

function my_function(x)
    return x * global_var
end

end  # module MyModule

ブロック内では@__MODULE__マクロの値は更新される.

module MyModule

export my_function

const global_var = 42

function my_function(x)
    return x * global_var
end

println(@__MODULE__)

end  # module MyModule

println(@__MODULE__)
Main.MyModule
Main

my_functionMyModule.my_functionの外部からアクセス可能な関数になる.

export文は,この module をusingした時に,何が取り込まれるかを指定する.

exportしていなかったグローバル変数global_varはモジュール内部では直接参照できても,外部からはMyModule.global_varとしてアクセスしないといけない.

using .MyModule

result = my_function(2)
println(result)
84
println(MyModule.global_var)
42
println(global_var)
LoadError: UndefVarError: `global_var` not defined

module は入れ子式にできる.その際はA.B.fooというように参照する.

1.3 using文:既存の外部 Module から名前を輸入する

1.3.1 :演算子:個別の名前だけを選んで取り込む

using Statistics: mean, std
using Statistics: Statistics

とすると,Module 内部の変数・関数名は一切入れずに,Module 名だけ取り込む.

すると,Statistics.mean という形で利用できるようになる.using じゃ届かない import されていない名前も,全てこの方法でアクセスできる.1

1.3.2 using .MyModule

名前はLOAD_PATH変数に沿って検索される.

REPL で定義した直後の module は Main.Module になっており,LOAD_PATH が通っていないので,using Module と言われてもわからない.

この場合は,相対 path で読み込む必要がある..Moduleでアクセスできる...は親の子モジュール,...は祖父母の子モジュールにアクセスする.ShellScript と同じ要領である.

1.4 include文:ファイルの分割

include(String)

Stringを path として評価し,そのファイルを見つけ出し,Julia 文として評価する.

path の構文は / を用いる.2

include 関数を REPL で使うと,相対 path は working directory からのものと解釈される.

1.5 Import文:拡張を許す取り込み

またusing文と違って,exportに制御された暗黙の取り込みがない.

import Base: length

length(v::MyType) = 3

importを使わない方法:

Base.length(v::MyType) = 3

構文と:演算子はusingと同じ.

2 パッケージ

2.1 プロジェクトの作成

ディレクトリごと作成する場合は:

(@v1.10) pkg> generate MyPackage

既存のディレクトリを用いる場合は:

(@v1.10) pkg> activate .
(@v1.10) pkg> instantiate

既存のプロジェクトを有効にして REPL を起動する場合は

$ julia --project

この状態で

(MyPackage.jl) pkg> add Example

とすると,Project.tomlに依存関係が追記され,パッケージ内でusing Exampleとすることができるようになる.

2.2 プロジェクトの定義

プロジェクト(環境)とは,Project.tomlManifest.toml(任意)を備えたディレクトリのことをいう.

Project.tomlはプロジェクトが読み込む名前空間と識別子を定義する.

これらのファイルは抽象的には次の3つの写像を定めている:

  • roots : name::Symbol \(\Longrightarrow\) uuid:UUID

    パッケージ名nameに,一意なuuidを割り当てる.

    環境内でimport Xという構文を見つけた際,Julia は識別子 roots[:X] を検索する.

  • graph : context::UUID \(\Longrightarrow\) name::Symbol \(\Longrightarrow\) uuid::UUID

    roots とは違って,コンテクストによって変わり得る名前とUUIDの対応を定める.

  • paths : uuid::UUID \(\times\) name::Symbol \(\Longrightarrow\) path::String

    uuidnameの組に,パッケージのインストールされた場所を定める.

写像rootsProject.toml[deps]セクションによって定義される.

Footnotes

  1. これで指定しないと何を取り込んだのかの制御が外部にあるままなので(module 定義内のexport文),共同開発の時は指定するのが良い.↩︎

  2. Windows のように,Julia は/を使う.↩︎

  3. 日本語解説記事もある:Qiita (2023.9)↩︎