ジュリアのスプラットオペレータ
概要
Juliaで...
はスプラット・オペレーターと呼ばれ、関数を使用したり、配列を定義する際に便利に使われる1。このオペレーターはJuliaに限定されているわけではないが、他の言語に比べて直感的に定義されており、学びやすく覚えやすいところが突出している。個人的な経験だと、...
を使うようになるとJuliaプログラミングに関する何かしらの気づきを得る気がする。
コード
関数入力
基本的に...
は配列やジェネレータの後に付けて使い、そのまま前にあるコンテナ/イテレータの要素を全部展開して出す。
julia> min([1,2,3,4,5,6,7,8,9,10])
ERROR: MethodError: no method matching min(::Vector{Int64})
julia> min(1,2,3,4,5,6,7,8,9,10)
1
例えばJuliaのmin()
関数はリデュースとして働くから、そのまま配列を渡すのではなく、複数の数を直接引数として渡さなければならない。もちろん、配列が大きくなるほど手で全部解いて書くのは難しくなり、配列の要素を展開して入れることができるように...
を使うことができる。
julia> min(1:10)
ERROR: MethodError: no method matching min(::UnitRange{Int64})
julia> min((1:10)...)
1
もちろん、実際は配列に使えるminimum()
関数があるから、わざわざこうする必要はない。
配列定義
julia> [(1:10)]
1-element Vector{UnitRange{Int64}}:
1:10
上で定義された配列はユニットレンジの配列なので、直接要素にアクセスするのが少し面倒になる。時間があれば、ただ単に1から10までの数字を書き込んだらいいけど、スプラットオペレータを使えば、次のように簡単に定義できる。
julia> [(1:10)...]
10-element Vector{Int64}:
1
2
3
4
5
6
7
8
9
10
もちろん、collect()
関数のような代替手段もあるが、知っておくときれいでセンスがある表現だという点が魅力的だ。ただし、速度の面ではあまり推奨されていないので、必要以上に...
を使わないようにしよう。
julia> [eachrow(rand(3,3))...]
3-element Vector{SubArray{Float64, 1, Matrix{Float64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}:
[0.6695368164913422, 0.69695509795356, 0.12084083239135612]
[0.6833475867141307, 0.5368141950494666, 0.7877252857572066]
[0.2810163716135018, 0.04317485597011517, 0.44214186775440534]
...
が面白くなるのは、上のようにジェネレータを一度通るときだ。eachrow()
は行列を行単位に切ったベクトルのジェネレータをリターンし、スプラットオペレータを通じて、その各ベクトルを配列表記[]
に入れて、ベクトルのベクトルを作ったものだ。
全コード
min([1,2,3,4,5,6,7,8,9,10])
min(1,2,3,4,5,6,7,8,9,10)
min(1:10)
min((1:10)...)
[(1:10)]
[(1:10)...]
[eachrow(rand(3,3))...]
環境
- OS: Windows
- julia: v1.8.3