Open3

Juliaのパッケージ作成メモ

tkmfujisetkmfujise

Julia の REPL を立ち上げて以下を実行すると雛形ができる。
runtests.jl や github workflow やら documenter やら色々ファイルを作ってくれる。

using PkgTemplates
Template(interactive=true)("ここにパッケージ名")

作成される場所は ~/.julia/dev なので、他の場所に移したい場合は移した後に ~/.julia/dev/xxx にシンボリックリンクを張る。
ローカル環境で以下コマンドを流すことでインストールした扱いになり普通に using Xxx で使えるようになる。
向き先は開発中のパッケージフォルダなので、パッケージを変更してもアップデートは不要。

Pkg.development("ここにパッケージ名")

参考
https://github.com/JuliaCI/PkgTemplates.jl

tkmfujisetkmfujise

初めてのことなのでどう開発するのが正解なのかわからないが、
VSCode(Juliaアドオンインストール)で立ち上げたREPLを主に使っている。

どこか適当な行で何も選択せず ctrl + Enter を打って、VSCodeのターミナルにProject.toml を読み込んだ状態のREPLを立ち上げる。
このときキャプチャのように syntax: incomplete: premature end of input とエラーが出るが気にせず該当行で Esc を打って赤くなったハイライトを消す。

立ち上がったREPLで、

using Revise

を打って

using MyPkg

すると、リロードしなくても変更がREPLに反映される。

基本はREPLでごにょごにょコードを試しながらうまくいったらソースに書き写すみたいなことをしている。
(ブレークポイントとかの使い方は知らない)

仕事のRails開発では主にpryを使ってわからないことはオブジェクトに訊くみたいな感じでごにょごにょしてるが、Juliaはオブジェクト指向ではないので、データと振る舞いがカプセル化されているRuby(pry)と違って、REPL上の変数を捨てずに関数の定義を追加したり変更したりしても動くのがいいなと思った。(struct の変更はREPLの再起動が必要だけど)

テストは REPL上で ]test と打つと、test/runtests.jl が動く。
REPL上で ; と打つとシェルに入れるのは、ファイルを消したり移したりするのに使ったり、もろもろ便利。
JuliaのREPLは優秀だなと思った。

tkmfujisetkmfujise

以下のような感じでファイルを作っている。

src
├── including_functions.jl
├── MyPkg.jl
├── SomeModule1.jl
└── SomeModule2.jl

module を持たない function の集まりは snake_case.jl
module を持つものは PascalCase.jl にしている。

src/MyPkg.jl
module MyPkg

include("including_functions.jl")
include("SomeModule1.jl")
include("SomeModule2.jl")

function some_main_func()
end

end # module
src/including_functions.jl
function some_util_func()
end
src/SomeModule1.jl
module SomeModule1.jl

using ..MyPkg: SomeModule2
#using ..MyPkg: SomeModule2.bar ←これならbarを呼べるが。。
using .SomeModule2

function foo()
end
src/SomeModule2.jl
module SomeModule2.jl

export: bar

function bar()
end

include, import, export, using をどうするのが正解かわからないが、
パッケージ本体の MyPkg.jl にもろもろ include させてる。

各モジュール間で使いたい関数やら構造体を受け取りたい場合は、

using ..MyPkg: SomeModule2
using .SomeModule2

のようにしている。
パッケージ本体は .. とピリオド2つ。
使いたい関数やら構造体を持っているモジュールを . とピリオド1つで呼ぶ。

Xxx: Yyy のように : をつけると指定したものだけ呼べるが、さらにその下の Yyy が持っている関数や構造体は export で定義していても呼び出せず UndefVarError と怒られる。

MyPkg 側でも export 定義すれば呼べるんだろうがそれもやりたいことと違うので、
冗長だが

using ..MyPkg: SomeModule2

でパッケージ本体のうち使いたいモジュールを呼んで、

using .SomeModule2

で使いたいモジュールが持っている関数や構造体を持ってくる。

REPLでモジュールの中のコードを動かしたい場合は、

julia> using Revise
julia> using MyPkg
julia> using MyPkg.SomeModule1

とすると、 SomeModule1 が持っている関数やら構造体が展開されたREPLになるので、そこでごにょごにょする。