Julia体験してみた
ワイ
Scalaユーザ
Scalaはそこそこ詳しい
仕事ではTSがメイン
Julia
https://julialang.org
https://speakerdeck.com/antimon2/julia-toiuyan-yu-nituite-fp-in-julia-side-f-for-guan-shu-xing-maturi2025
https://docs.julialang.org/en/v1/ によれば
Julia features optional typing, multiple dispatch, and good performance, achieved using type inference and just-in-time (JIT) compilation (and optional ahead-of-time compilation), implemented using LLVM. It is multi-paradigm, combining features of imperative, functional, and object-oriented programming.
もともと、リサーチャーはPythonとかを使っているが遅く、本気で計算を回すとなるとFORTRANやCに書き直さなければならない・・・という"Two Language Problem"の解消を正面きって目指した言語
PythonはNumpyなどに計算コアを逃がしてそこだけFORTRANで速くするみたいなことをやった
Juliaは最初から爆速の動的言語を作るという使命を負って産み落とされた
目玉機能
Scalaなかよしポイント
JITがある
マルチパラダイム
FP的機能もある
全ては式
ファーストクラスな関数
nominal typing
メタプロ得意
Scalaとは違うポイント
配列のインデックスが1始まり
動的型付け
型の表記の省略もできる
マルチディスパッチ
全てのコードがLLVMによってJITコンパイルされるため高速
JVMではホットスポットだけJITコンパイルする
型が確定したタイミングでJITコンパイルが走るので型を省略しても問題ない
事前コンパイルするような芸当も可能
最初から並列・並行プログラミングのサポートが手厚い
パターンマッチはない
ライブラリで対応
ここはTSと同じやな
パイプライン演算子|>あり
インストール
Scalaより簡単
https://docs.julialang.org/en/v1/manual/installation/
curl -fsSL https://install.julialang.org | sh
個人的にこのスタイルはあまり好きではないが・・・
スクリプトを直接シェルに流し込むのまあまあ怖い
ScalaはJVMのインストールもいるからなぁ・・・
code:sh
% julia
_
_ _ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type "?" for help, "]?" for Pkg help.
| | | | | | |/ _` | |
| | |_| | | | (_| | | Version 1.11.5 (2025-04-14)
_/ |\__'_|_|_|\__'_| | Official https://julialang.org/ release
|__/ |
julia> println("yo")
yo
Julia REPL
juliaでREPLが起動する
julia foo.jlするとそれを実行できる
Juliaの拡張子は.jl
C-dで終了できる
パッケージマネージャやビルドツールが統合されているのが偉い
とりあえずたらいまわし関数を実装する
code:tarai.jl
tarai(x,y,z) = x <= y ? y : tarai(tarai(x-1,y,z), tarai(y-1,z,x), tarai(z-1,x,y))
こういう風にf(x) = ...の形で簡潔に関数を定義する記法がある
function f(x)と書くのが正式
code:julia
julia> tarai(10,5,0)
10
たしかに速い
@timeを使うと時間計測ができる
便利
code:time
julia> @time tarai(12, 6, 0)
0.034373 seconds
12
対照実験: rubyで同様にする
code:tarai.rb
def tarai(x, y, z) = if x <= y then y else tarai(tarai(x-1,y,z), tarai(y-1,z,x), tarai(z-1,x,y)) end
code:time
require 'benchmark'
t = Benchmark.measure do tarai(12,6,0) end
t.real
=> 0.5449444850000873
10倍以上速い
対照実験: Scalaでもやってみる
code:tarai.scala
def tarai(x: Int, y: Int, z: Int): Int =
if x <= y then y else tarai(tarai(x-1,y,z), tarai(y-1,z,x), tarai(z-1,x,y))
def measureTarai(x: Int, y: Int, z: Int): (Int, Double) =
val t1 = System.nanoTime
val result = tarai(x,y,z)
val duration = (System.nanoTime - t1) / 1e9d
(result, duration)
code:time
scala> measureTarai(12, 6, 0)
val res5: (Int, Double) = (12,0.041759119)
いい勝負
おもしろいところ
他の言語では2 * xと書くところ、2xと書ける
科学計算のために生まれた言語なだけある
UInt128のようなバイナリ的に厳密な便利な型がある
Scalaにはない
≈演算子
近似等価
コレクション操作
Juliaでは基本的なコレクションは配列(Array)
https://docs.julialang.org/en/v1/manual/arrays/
型名としてはVector
他の言語と同じようにArray Literalがある[1,2,3,4]
Scalaにはコレクション専用のリテラルはない
そういう思想
多次元ベクトル(行列)もネイティブにサポートされるし、専用のリテラルがある
カラムベースなのでそういう処理の場合速い
スペースで区切ると列が区切られる
[1 2 3 4] => 1x4行列
改行で区切ると行が区切られる
code:mat.jl
[1 2
3 4]
=> 2x2行列
ちなみに、この改行は;で置換してよい
code:mat.jl
1 2; 3 4
=> 2x2行列
組込みで便利グッズがある
m = [1 2; 3 4]
m * m (積)
transpose(m)
using LinearAlgebra
eigvecs(m)
eigvals(m)
配列と行列の共通操作として.関数がある (element-wise operation)
xs .* 2とすると、xsの全要素に* 2したのと同じことになる
f(x) = -xのとき、f.(xs)もできる
便利!!!
ドキュメント進めていく
Julia/Variables
Julia/Integers and Floating-Point Numbers
Julia/Mathematical Operations and Elementary Functions
Julia/Complex and Rational Numbers
Julia/Strings
Julia/Functions
Julia/Control Flow
Julia/Scope of Variables