UEFN Verse言語 メタバース

【UEFN】パラメトリック型とは?型引数や共変反性・制約【Verse備忘録】

パラメトリック型とは

パラメトリック型は、ジェネリック型やテンプレート型とも呼ばれ、汎用的なデータ構造や操作を定義するための仕組みです。

型引数を受け取ることができるため、さまざまなデータ型に対して再利用可能なコードを書くことができるのが特徴的。

プログラム内でパラメトリック型を使用する場合、型引数として具体的なデータ型を指定する必要があります。

これにより、同じコードを異なるデータ型に対して使用することができますね。

例えば、リストを表すパラメトリック型を考えてみましょう。

リストは様々なデータ型の要素を保持できるため、パラメトリック型を使用することで、整数のリストや文字列のリストなど、異なるデータ型のリストを作成できます。

これにより、リストに関連する操作やアルゴリズムを再利用することができます。

あすか
 例

明示的な型引数

明示的な型引数は、関数やクラスの定義時に指定される型の引数のことを指します。

これにより、特定のデータ型に対して関数やクラスを作成できますね。

あすか
box(first_item:type, second_item:type) := class:
    ItemOne:first_item
    ItemTwo:second_item

例えば、上記のコードでは、boxというクラスが定義されています。

このクラスは2つの引数を受け取り、それぞれの引数の型はtypeです。

first_itemはItemOneクラスのインスタンスを、second_itemはItemTwoクラスのインスタンスを初期化。

ここで、first_itemとsecond_itemは明示的な型引数であり、boxクラスを特定のデータ型に対して作成するために使用されます。

MakeOption(t:type):?t = false

IntOption := MakeOption(int)
FloatOption := MakeOption(float)
StringOption := MakeOption(string)

また、使用例として、string型の値を持つboxやint型の値を持つbox、またはstring型とint型の値を持つboxなど、異なるデータ型に対してboxクラスのインスタンスを作成することができます。

MakeOption関数は任意の型を引数として受け取り、その型のoptionを返すのが特徴的。

明示的な型引数があり、特定のデータ型に対してoptionを作成するのに使用されます。

例えば、int型のoptionを作成するためにはIntOption := MakeOption(int)というコードを使用します。

このようにすることで、MakeOption関数はint型に対してoptionを生成するための関数となります。同様に、float型のoptionやstring型のoptionを作成することもできますね。

 メモ用

明示的な型引数は、プログラム内で特定のデータ型に対して再利用可能なコードを作成する際に便利です。

あすか
りゅう

具体的なデータ型を指定することで、関数やクラスを型に特化させることができるってことですね!

暗黙的な型引数

暗黙的な型引数は、関数やクラスの定義時に specific な型を指定せずに、任意の型に対して機能するコードを作成するために使われる仕組みです。

暗黙的な型引数は where キーワードを使用して導入されます。

ReturnItem(Item:t where t:type):t = Item

例えば、上記のコードでは、関数 ReturnItem() が定義されています。

この関数は Item というパラメータを受け取り、その型を暗黙的な型引数 t で制約し(where t:type)、ReturnItem() 関数は受け取った引数 Item をそのまま返します。

このとき、t は関数 ReturnItem() の暗黙的な型パラメータであり、どんな型でも受け取ることができます。

ただし、t の型に基づいて、ReturnItem() 関数が受け取ることができる Item の型が制約されます。

つまり、ttype という制約があるため、どんな型でも ReturnItem() を呼び出すことができるわけです。

あすか

暗黙的な型引数を使用することで、ReturnItem() を以下のように書く必要はありません。

ReturnInt(Item:int):int = Item

ReturnFloat(Item:float):float = Item

代わりに、1つの関数で済ませることができます。

ReturnItem(Item:t where t:type):t = Item

これにより、ReturnItem() 関数は実行する操作に関係なく、t の型に基づいて正しく機能します。

ReturnItem("t") # t は文字列です
ReturnItem(0.0) # t は浮動小数値です

実際の使用例として、ReturnItem() 関数が引数として "hello"0.0 を受け取った場合を示しました。この場合、t はそれぞれ文字列型と浮動小数点型になります。

box(first_item:type, second_item:type) := class:
    ItemOne:first_item
    ItemTwo:second_item

MakeBox(ItemOneVal:ValOne, SecondItemVal:ValTwo where ValOne:type, ValTwo:type):box(ValOne, ValTwo) =
    box(ValOne, ValTwo){ItemOne := ItemOneVal, ItemTwo := SecondItemVal}

Main():void =
    MakeBox("A", "B")
    MakeBox(1, "B")
    MakeBox("A", 2) 
    MakeBox(1, 2)

同様に、MakeBox() 関数も暗黙的な型引数の例です。

この関数は2つの引数 ItemOneValSecondItemVal を受け取り、それぞれの引数の型を暗黙的な型引数 ValOneValTwo で制約(where ValOne:type, ValTwo:type)。

そして、MakeBox() 関数は引数の型に基づいて決まる型のボックスを生成して返します。

 box(first_item:type, se~の詳細

このように暗黙的な型引数を使用することで、特定のデータ型に依存せずに再利用可能なコードを作成できるのが特徴です。

あすか
みなみ

暗黙的な型引数によって、特定の型に制約されずに幅広いデータ型に対して機能する柔軟なコードを書くことができるわけですね🌸

型の制約

▼ 型の制約を指定することで、式の型に制約をかけることができます。

現在、サポートされている制約はサブタイプのみであり、暗黙的な型パラメータのみが対象となります。

これにより、与えられたクラスが特定のクラスのサブクラスである場合にのみ関数がコンパイルされるようにできます。

例えば以下のとおり。

int_box := class:
    Item:int

MakeSubclassOfIntBox(NewBox:subtype_box where subtype_box:(subtype(int_box))) : tuple(subtype_box, int) = (NewBox, NewBox.Item)

タプルとは

タプルとマップの違い

用語集

型マクロとは

まとめ

2023/7/12 お疲れさま。

  • この記事を書いた人
  • 最新記事

あすか(Asuka)

自己紹介:UEFNクリエイター兼ブロガー
Verse言語独学中 | UE・プログラミング・3Dモデリング完全初心者 | 備忘録として学習記録をブログに残しています。
■好きな言葉
徳は弧ならず必ず隣あり.
■ひとこと
まだまだ未熟者ですが、
よろしくお願いします。

-UEFN, Verse言語, メタバース
-, ,