パラメトリック型

2026年3月21日
1 分

パラメトリック型とは、他の言語でジェネリクスとかテンプレートとか呼ばれている機能と似たものだ。 次のように定義する。

julia> struct Point{T}
         x::T
         y::T
       end

T を型パラメータと呼び、Point{T} は「T をパラメータとする Point 型」といえる。 T はインスタンスを生成するときに、具体型の Int とか Float64 とかに決まる。

julia> p = Point(2, 3)
Point{Int64}(2, 3)

julia> q = Point(2.2, 3.7)
Point{Float64}(2.2, 3.7)

または、p = Point{Int}(2, 3) のように型を指定してもいい。

昨日の記事で、フィールドの型ごとに PointPointF に分けていた複合型を Point{T} ひとつにできるわけだ。

関数も型パラメータをとるように書ける。 原点からの距離を計算する distance 関数を定義してみよう。

julia> function distance(p::Point{T}) where T
         sqrt(p.x^2 + p.y^2)
       end
distance (generic function with 1 method)

引数の型に Point{T} を指定するだけでなく、後ろに where T とつける必要がある。ちゃんと動作するか試してみる。

julia> p
Point{Int64}(2, 3)

julia> distance(p)
3.605551275463989

julia> q
Point{Float64}(2.2, 3.7)

julia> distance(q)
4.304648650006177

もし、Point{Int}Point{Float64} で関数本体部分を異なる実装にしたいときには、多重ディスパッチをつかう。

function distance(p::Point{Int})
  # Int の時の実装
end

function distance(p::Point{Float64})
  # Float64の時の実装
end

さて、2点間の距離を計算する distance2 関数(昨日の記事で書いた distance)を書いてみよう。上の pq を引数にとれるようにするには、型パラメータを2つにする必要がある。なぜなら pq では型が違うから。次のようにする。

julia> function distance2(p1::Point{T}, p2::Point{U}) where {T,U}
         sqrt((p1.x - p2.x)^2 + (p1.y - p2.y)^2)
       end
distance2 (generic function with 1 method)

型パラメータが2つ(以上)ある場合には where {T,U} のように、{ } をつける。 また、ここでは型パラメータに TU を使っているけど、これは決まった文字があるわけではないので T1T2 とかでも構わない。

では試してみよう。

julia> p
Point{Int64}(2, 3)

julia> q
Point{Float64}(2.2, 3.7)

julia> distance2(p, q)
0.728010988928052

pq を逆にしてもちゃんと動作する。

julia> distance2(q, p)
0.728010988928052