Juliaのpackage extensionを試す
Julia v1.9からPackage extensionsが導入された。Juliaのパッケージ依存には
- Strong dependency: 依存先のパッケージBの機能を当該パッケージAで使用するもの
- Weak dependency: 依存先のパッケージCに関連したメソッドを当該パッケージA内で多重ディスパッチで追加するもの
の2種類がある。パッケージAを読み込んだときにパッケージBは読み込まれる必要があるが、Weak dependencyであるところのパッケージCは本来は読み込まれる必要はない。これを解決する手段がPackage extensionである。
本スクラップでは私の自作パッケージに関してpackage extensionsを適用する試行錯誤を記録する。
とりあえず現状の疑問点として:
-
Project.toml
に記載する[weakdeps]
は古いJulia(LTSのJulia v1.6など)でも正常に読み込めるのか? -
[extensions]
に記載するパッケージの命名規則は? - パッケージDで型
Foo
を定義してパッケージEで関数bar
を定義しているとする。bar(::Foo)
メソッドはパッケージD内のextensionsとして書くべきか、あるいはE内で書くべきか?
- BasicBSpline.jlで取り組むissue: https://github.com/hyrodium/BasicBSpline.jl/issues/328
- 公式ドキュメント: https://pkgdocs.julialang.org/v1.9/creating-packages/#Conditional-loading-of-code-in-packages-(Extensions)
- IntervalSets.jlでのPR例: https://github.com/JuliaMath/IntervalSets.jl/pull/146
BasicBSpline.jlで取り組むissue
については https://github.com/hyrodium/BasicBSpline.jl/pull/334 で解決しました。
Project.toml
に記載する[weakdeps]
は古いJulia(LTSのJulia v1.6など)でも正常に読み込めるのか?
JuliaではProject.toml
に含まれる無関係なセクションは無視される。古いバージョンのJuliaも例外ではなく、単純に[weakdeps]
は無視される。メソッドの追加に関しては
if !isdefined(Base, :get_extension)
include("../ext/PlottingContourExt.jl")
end
のように読み込む。詳しくは公式ドキュメント参照。
注意: [deps]
はstrong dependenciesではなく、strong dependenciesとweak dependenciesを合わせたセクションとして扱う。
[extensions]に記載するパッケージの命名規則は?
"$(MyPackage)$(WeakDepPackage)Ext"
のような命名規則でモジュールを追加する。そのモジュールは$(MyPackage)/ext/$(MyPackage)$(WeakDepPackage)Ext.jl
に書く。
パッケージDで型
Foo
を定義してパッケージEで関数bar
を定義しているとする。bar(::Foo)
メソッドはパッケージD内のextensionsとして書くべきか、あるいはE内で書くべきか?
DでもEでもどちらでもOK。
- どちらのパッケージの方が知名度があるか
- どちらのパッケージの方がメンテナのやる気があるか
などで決まってくる。
追加するメソッドが違ったとしてもPackageAPackageBExt
とPackageBPackageAExt
は同時に存在できないことに注意。
新たな疑問。
- PkgA.jlとPkgB.jlがそれぞれ
func_a
とTypeB
を定義している - PkgAとPkgBの間には依存関係が無い
- MyPkg.jlで
func_a(::TypeB, ::MyPkg.MyType)
を定義したい
このとき、「PkgAとPkgBが同時に読み込まれたときにだけロードされるようなextensions」は作れるか?
JuliaCon2023でのPackage extensionsの発表動画です
疑問が1つ残ったままだが、JuliaTokaiでの発表まで終わったのでcloseします
JuliaTokaiの発表資料で
- Aqua.jlのProject.tomlフォーマッティング
- v1.6とv1.9で自動フォーマッティングの形式が異なる
- v1.9のみでAquaのテストを走らせるように変更
と記載していたが、これに関してはAqua.jlで修正される予定の様子
このとき、「PkgAとPkgBが同時に読み込まれたときにだけロードされるようなextensions」は作れるか?
https://github.com/JuliaGraphics/Luxor.jl/pull/276 でそれっぽいことしてるので後で確認する
注意: [deps]はstrong dependenciesではなく、strong dependenciesとweak dependenciesを合わせたセクションとして扱う。
勘違いで、[weakdeps]⊆[deps]
でなくてok。v1.8以前のJuliaに対応するために必要な手法だった
weakdepsのためのメソッドを定義したい場合にのみパッケージをロードできる?
具体的にはForwardDiff.jlをweakdepsにして、MyPkgForwardDiffExt.jlの中でForwardDiffChainRules.jlに依存できるか?