前書き

Verse言語の機能の一つに「オプション型」というものが存在します。これを超簡単に説明すると「存在する」か「存在しない」の二つの状態を持つ変数のことです。どういうこっちゃという方のために、簡単な例を紹介しましょう。

オプション型

sample_device := class(creative_device):

    @editable
    RegisterButton:button_device = button_device{}

    @editable
    UnregisterButton:button_device = button_device{}

    @editable
    PointProp:creative_prop = creative_prop{}

    var MaybeTarget:?agent = false

    OnBegin<override>()<suspends>:void=
        RegisterButton.InteractedWithEvent.Subscribe(OnInteractRegister)
        UnregisterButton.InteractedWithEvent.Subscribe(OnInteractUnregister)

        loop:
            Sleep(10.0)
            if:
                Result := MaybeTarget?
                FortCharacter := Result.GetFortCharacter
                PointProp.TeleportTo[FortCharacter.GetTransform()]
            then:

    OnInteractRegister(InAgent:agent):void=
        set Target = option{InAgent}

    OnInteractUnregister(InAgent:agent):void=
        set Target = false

オプション型の変数の作り方は非常に簡単で、型の左隣に「?」をつけるだけです。今回のサンプルコードの場合、「MaybeTarget」の部分がオプション型の変数となります。

先ほども述べたように、オプション型は「存在する/存在しない」の二種類の状態を持つ変数です。この「存在する」状態にするためには、変数に対して「= option{値}」で値をセットすることで行えます。OnInteractRegister関数内ではボタンを押した対象が「InAgent」の変数に格納されているため、それをグローバルな空間にある「MaybeTarget」にセットする処理を行っています。

if:
    Agent := MaybeTarget?
then:
    # Agentを使用する

オプション型に入れた値は、そのままでは使用できません。オプション型は「値が存在しない」可能性があるため、そのまま使用すると無に対して何か動作をしようとしてしまうからです。

そのため、失敗コンテキスト(if等)内でオプション型の変数に対して「?」を右隣に付け加えてあげると、「存在するかの確認」と「値の取り出し」が同時に行われ、値を実際に使える状態にできます。

if:
    FortCharacter := MaybeTarget?.GetFortCharacter[]
then:

のように、「?」の部分自体が取り出した値になっているため、それ以降に続けて関数を呼び出すこともできます。

OnInteractUnregister(InAgent:agent):void=
    set Target = false

少し戻って「OnInteractUnregister」の処理も見てみます。先ほどはオプション型に値をセットすることをしましたが、その逆の「値を取り消す」方法についても紹介します。こちらは非常に簡単で、オプション型の変数に対して「= false」と記述するとオプション型内の値が無くなります。

つまり、

if:
    Result := MaybeTarget?
    FortCharacter := Result.GetFortCharacter
    PointProp.TeleportTo[FortCharacter.GetTransform()]
then:

の部分の処理は実行されないことになります。なぜかって?

オプション型の変数に対して「?」と右隣に書いてあげると、「存在するかの確認」と「値の取り出し」が同時に行われるといいました。もし値が存在しないのであれば、その値に対して関数などでの追加の処理を行うこともできません。つまり、処理は実行できないと判断され、if内の処理はキャンセルされてthenの部分まで進まないということです。もしelseが用意されていれば、そちらが実行されます。

まとめ

オプション型は「?型名」で定義する

var MaybeNumber:?int = false
var MaybeNumber:?int = option{56}

オプション型の定義は「?型名」を用いて行えます。初期値は空を示すfalseか、実際の値を入れるoption{値}の二種類です。

実際に取り出して使う

if:
    Number := MaybeNumber?
then:
    Print("{Number}が取り出された")
else:
    Print("値が空だ")

オプション型は一度値を取り出す作業が必要です。取り出すためにはifなどの失敗コンテキスト内で、「変数?」の形式で行います。もし値が入っていればthen部分まで処理が進み、Numberには実際に入っていた値が入ります。もしfalseの場合であれば、処理が実行されずelseの部分に進みます。

値をセットする

set MaybeNumber = false
set MaybeNumber = option{56}

変数に対して「false」とすると中身を空にすることができます。逆に、「option{値}」とすると中身を入れることができます。