プログラミング言語 Julia を組織に導入する際聞かれる FAQ

# 本日は

Julia アドベントカレンダー2024

https://qiita.com/advent-calendar/2024/julia

の Series 2 です．Series 1 は多くの方に書いていただきました．ありがとうございます（ペコペコ）．

Series 2 は裏アドベントカレンダー的なノリで書いてみようと思います．Juliaについてよく聞かれることについての Question とそれに対する個人の一つの Answer を書いてみようと思います．主に Python は知ってる・使っている方向けの説明になっています．

## Julia について

14 February 2012 に Why we created Julia というブログが開発者から公開されました．

https://julialang.org/blog/2012/02/why-we-created-julia/

公開から 12 年ほど経過しています．他のプログラミング言語に比べると若い方の部類です．

Announcing the release of Julia 1.0 が 2018 年に発表されているので仕様が安定し 6 年ほど経ちました．

https://julialang.org/blog/2018/08/one-point-zero/

いくつかのアップデートを通じて v1.11.2 が最新安定版，LTS が v1.10 となっています．ユーザとして使う場合は定期的にリリースされる最新安定版を使うようにします．

`1.0` 系が出たばかりではいくつかのライブラリが動かない．．．といったトラブルはありましたが，今は最初の導入ではコケることはそこまでないように思えます．

Julia は JIT コンパイル方式で動作します．関数が初回に呼ばれる際その関数に対するコンパイルが実行され LLVM を経由して各プラットフォームに最適なネィテイブコードを生成します．

荒っぽい言い方をすれば Python の任意のコードに対して Numba が適用でき高速に実行することを可能とする世界を Julia は提供します．

適切にプロファイルを取り型安定なコード，メモリアロケーションを抑制するコードを書けば C++ の O2 最適化程度に高速できます．ベンチマークを取得しボトルネックになる箇所を探し改善するワークフローは VS Code のエコシステムでスムーズに実現ができます．

Julia には REPL が備わっています Python でいえば IPython のようなものです．Julia の REPL を使うことで

- コードの実行
- ライブラリのインストール
- ドキュメント（マニュアル）を読む
- 簡単なシェルコマンドの実行

ができます．Python はインデントの深さでコードのブロックを表現する都合上，本格的な関数を書くためには Jupyter などエディタを起動しないと行けませんが，Julia はそのような制限はありません. Alt ＋ Enter でコードを評価せず改行しながら複数行の関数を書くこともできます．　`;` で繋げて下記のように複数の式を一列に書くこともできます．

```julia
julia> using Plots; plot(sin); savefig("sin.png")
```

従って基本的な文法の学習は REPL で済ますことができます．

REPL の上で実行する場合は上記の `julia>` （プロンプトと言います）を含めてコピーアンドペーストをすることができます．そうすると REPL 側がいい感じに処理し `using Plots; ...` の部分を評価・実行してくれます．

## Julia の面白いところ

- コードを数式に対応させやすいところです．Unicode 文字入力を支援する機能が備わっています．例えば下記のような文字を変数名として使うことができ, TeX に慣れていれば `\alpha`を入力して Tab キーを入力すると `α` として変換されます．日本語の変換で「アルファ」と入力しスペースキーで変換候補を探して `α` を出してもOKです．

```julia
julia> α β x₁ N² Σₖ
```

`π` は円周率として使うことができます．数値の後の積演算子 `*` は省略することができます．

```julia
julia> 2π # 円周率の2倍を計算
6.283185307179586
```

この意味で紙と鉛筆の世界に慣れている理学系のコミュニティと親和性があるように思えます．

また `@code_lowered, @code_llvm, @code_native` などのマクロを使うことで自分のかいたコードがどのようにコンパイルされるのかという過程を見ることができます．

「このように書いたら速くなるかな？」などを検証する際に変更前後の差分を見て「あー，なるほど？ちょっと違う」というような観察ぐらいはできるようになります．

また，高速な実装を提供することを大事とする Julia はユーザが書いたコードを最適化するために力を入れています．また，最近は `juliac` という Julia によって書かれたコードを実行形式にするコンパイラドライバの開発も進んでいます．

その意味で普段そういう領域に興味がなくてもトピックは転がってくるので科学技術計算という高級なレイヤーを支える計算科学の領域の情報にアクセスできる機会もあります．

ちなみに今は JuliaHub (Juliaの開発元）がコンパイラーに詳しい方の人材募集されているようです．JIT コンパイラをいい感じにしたい人は応募してみると良いでしょう．

## Pyhon ユーザ側の学習コスト

- REPL
- Jupyter Notebook
- Pluto

のような対話形式で実行できる環境は用意されています．Jupyter Notebook は慣れていると思うのでそこから入るのもアリですが，Pluto はオススメです．一回ハマると元に戻れません．それぐらい快適です．

また PythonCall という Julia から Python を呼ぶ仕組みがあるので Julia を書きながら Python であったアレを使いたいという欲求を満たし参入のコストを下げることができます．

逆に PythonCall の双対パッケージとして juliacall という Python ライブラリがありますこれを使うことで　Julia コードを Python ライブラリとしてみなすことができます．なのでアルゴリズムを Julia で使ったが諸事情で Python に戻るば愛も出戻りのコストも最小限に抑えることができます．

この意味では PoC として導入する際の技術的・心理的障壁は低いように思えます．

また HTTP.jl，Oxygen.jl を使うことで API サーバを作ることができます．FastAPI を使ったことがある人であれば Oxgen.jl を使った実装は馴染みやすいと思います．

また Plotly/Dash に慣れている方であれば Plotly.jl/Dash.jl を使う選択肢もあります．

まずは使ってみてください．インストールも `uv` の導入ぐらいに楽です．

---

## C/C++ との連携

- Julia は C-API を持っているので C から呼ぶこともできます．
- 一方で `ccall` を使うことで共有ライブラリにある機能を呼び出すと言うこともできます．

C++ では CxxWrap があります．Pybind11 に相当するライブラリです．WrapIt はヘッダーを自動生成する機能を持つライブラリです．最近では jluna と呼ばれるライブラリが出ており C++ から Julia を呼ぶためのライブラリも開発が進んでいます．

---

### 型システムの恩恵

Juliaでは関数の引数に型アノテーションを付与し意図しない入力を抑制することができます．

```python
def f(x: str, y: str):
    return x + y

f(1, 2) # 一応動く
```

Python では開発者側が意図しない使い方を防ぐために mypy, Pydantic などサードパーティの機能を利用する必要があります．これはこれで便利ですがエコシステムごとの学習コストがかかります．

一方で Julia では型システムがあるので `f` を作った人は `f(1, 2)` という使い方を阻止できます．

```julia
julia> function f(x::AbstractString, y::AbstractString)
    x * y
end

julia> f(1, 2) # エラーが起きる
ERROR: MethodError: no method matching f(::Int64, ::Int64)
The function `f` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  f(::AbstractString, ::AbstractString)
   @ Main REPL[6]:1

Stacktrace:
 [1] top-level scope
   @ REPL[7]:1

julia> f("Hello", "World")
"HelloWorld"
```

このように`x*y` を評価する前に `MethodError` で止めることができます．また，型付与は必須でなく多重ディスパッチ，可読性向上のために使われます．従って無理して全ての引数に型をつけるといった作業から解放され型を明記せず書くこともできます．これはプログラミングの初学者にとってありがたいことです．必要に応じてあとから学ぶことができるからです．

## 開発ワークフロー

パッケージを作る際はディレクトリ構造に決まりがあります．テストを含める場合は下記の構成が最小構成です．

```julia
Project.toml
src/MyPackage.jl
test/runtests.jl
```

ユニットテストを書く場合は `using Test` をロードし `@test <trueになって欲しい>` 事柄をツラツラ書いていきます．

効率良く開発を進めるには ReTestItems.jl を使ったテストフレームワークがあります．これは `@testitem begin ... end` 単位でテストをすることができこの単位で並列でテストの実行が可能です．また Julia の VS Code の Julia extension と VS Code の Testing の機能と連携することで特定のテストを実行することができます．

また，GitHub Actions のテンプレートが公開されているのでそれをコピペすればCI/CDによるワークフローが出来上がります．

## Julia は趣味でやっているのか？

これは難しい質問です．

何人かから聞かれるのでこの機会に答えておきます．金銭を目的とせずに行うことを「趣味」とすればOSSとしてコードを公開すること・Qiita ,Zennのような技術ブログでノウハウを公開することは趣味です．

仕事で Julia を使いたいので使う際に必要な障壁を取り除くための要素技術の開発を公開していると思っていただいて構いません．大学で言うところの基礎研究に近いものです．

一方で，企業・大学・学生からの依頼で講演，Julia のコードを書いて納品，技術指導をし対価・報酬をいただくという実績もあるのでプロでやってる側面もあります．

「大学で研究されてらっしゃるんですね．趣味を楽しまれて羨ましいです」と言って顔をしかめなければ私の活動は「趣味」と呼んで結構です．

## なぜ Julia を使っているのか

- REPL を使った対話方式で学習を（試行錯誤）したい
- 変数名にUnicodeが使えて数式と実装の乖離を抑制できる
- 自分は数理的な側面が強い高級なレイヤーで活躍ができる
- 一方，Julia はコンパイラの知識も流れてくるのでそういう話も触れられることができる
- ユーザがアカデミックな側面を持っている方が多い．国内では理学系の人が使ってるのでそう言う方達の文化に自分が馴染みやすい
- 民間で培ったエンジニアリングの知識を Julia コミュニティに還元できる
- パッケージは（まだ）ブルーオーシャン
    - 欲しい機能は作れば良い
    - パッケージ名をつけられるのは著者の特権
    - 作ったパッケージを拙い英語で宣伝するとスターがつく→嬉しい
- 速度向上の目的で C/C++/Fortran のような開発時にコンパイルを実施しなければいけない言語の選択に強いられたくない
- 多重ディスパッチの存在
    - Python で if isinstance 地獄なコードを作りたくない・読みたくない

## 興味を持っていること

- オレオレマクロの作成
- REPL の中身
- Rustとの連携
- Rust への移植，Rustからの移植