🐙

Verse言語の設計思想を読み解きたい(5)失敗コンテキスト:③decidesエフェクト指定子を付与した関数(メソッド)のボディ

2023/04/07に公開

前回はこちら。

https://zenn.dev/t_tutiya/articles/bc1641e4de71b9

今回は失敗コンテキストの関数編です。

関数(メソッド)

https://dev.epicgames.com/documentation/ja-jp/uefn/functions-in-verse

Verseではファイルスコープで定義されている関数を「関数(function)」、クラスメンバ定義されている関数を「メソッド(method)」と呼び分けています。ここでは関数に限った話をしていますが、失敗コンテキストに関して両者に差はありません[1]

失敗コンテキスト:③decidesエフェクト指定子を付与した関数(メソッド)のボディ

decidesエフェクト指定子を付与した関数(メソッド)の「ボディ(body. 関数の実装部のこと)」は失敗コンテキストです。「ボディ」に限定されているのは、呼び出し時の引数などには失敗許容式を使えないという意味かと思われます。

Verseでの関数定義のサンプルコードを以下に示します。

Fail()<decides> : void = false?

Fail関数は引数無し、戻り値無し(void)、decidesエフェクト指定子が付与され、実装は"false?"のみです。この関数は呼びだすと常に失敗するという挙動を取ります。

ここでは失敗コンテキストに関係ある「エフェクト指定子」と「クエリ演算子」について見て行きます(関数自体の説明は別記事で予定)。

エフェクト指定子

Verseでは識別子(例えば関数名)や特定の予約語(例えば"class")に対して、「指定子(Specifier)」を付与することで、それらの振る舞い(behavior)を制御[2]出来ます。

https://dev.epicgames.com/documentation/ja-jp/uefn/specifiers-and-attributes-in-verse

指定子は"<>"で囲まれていて、付与出来る対象や位置によって種類が異なります。decides
は「エフェクト指定子(Effect Specifiers)」の一つです。「エフェクト指定子」という名称は、関数の呼び出し元が受け得る効果(effect)を指定するという意味だと思いますが、明示はされていません。

decidesエフェクト指定子が付与された関数は、失敗許容関数になります。失敗許容式を含む(つまり、失敗する可能性がある)関数を実装する場合には、必ずdecidesエフェクト指定子を付与しなければなりません。

クエリ演算子

https://dev.epicgames.com/documentation/ja-jp/uefn/operators-in-verse
下記のように、logic型(C#でのbool型)を返す式に後置(postfix)で記述された"?"は、「クエリ演算子(Query Operator)」と呼びます[3]

expression?

サンプルコードでは、logic型のfalseを返す予約語"false"にクエリ演算子"?"を後置しています。クエリ演算子を含めた式全体を「クエリ式(Query expressions)」と呼びます。

expressionがtrueを返した場合、クエリ式は成功します。この時、クエリ式はtrueを返します。
逆に、expressionがfalseを返した場合、クエリ式は失敗し、呼び出し元に失敗が伝播します。成功した場合と異なり、この時クエリ式は値を返しません。

もう一度サンプルコードを見てみます。

Fail()<decides> : void = false?

verseでは、スコープの最後に評価された式の結果が値として返ります(rubyと同じですね[4])。

logic型falseは当然ながらfalseを返すので、クエリ式は失敗します。結果、Fail関数は常に失敗します。

補足:desidesエフェクト指定子について

※2023/04/13追記:この項の説明は正確ではありませんでした。後ほど修正予定です。

verseの言語仕様では、関数にdesidesエフェクト指定子を付与する場合、本来は以下のようにtransactエフェクト指定子も同時に付与する必要があります。

Fail()<transacts><decides> : void = false?

transactは、その関数がトランザクション処理においてロールバックの対象となる事を明示するためのエフェクト指定子です。desides使用時にtransactが必要なのは、失敗許容関数はトランザクション処理されるルールなので、当然と言えば当然と言えます。

しかし、公式ドキュメントのサンプルコードではdesidesが単体で記述されている物が散見され、実際これでコンパイルも通るようです[5]

想像ですが、「常に両方付与する必要があるなら、省略しても同じでしょう?」という提案があり、実際そのように仕様が変更された(が、ドキュメントは更新されてない)のではないかと勝手に思っています。

続き

https://zenn.dev/t_tutiya/articles/ab81ba020dd983


verse言語とUEFNの記事を他にも書いているので御覧下さい。
https://zenn.dev/t_tutiya

最後まで読んで頂きありがとうございました。この記事がお役に立てたようであれば、是非LIKEとフォローをお願いします(今後の執筆のモチベーションに繋がります)。

#Verse #UEFN #Fortnite #Verselang #UnrealEngine

脚注
  1. 多分 ↩︎

  2. ドキュメントでは説明(describe)となっているので、直接制御するだけではなく、ヘルパー的な目的にも使われるのかも ↩︎

  3. "?"は別の用途で使用される事もあります ↩︎

  4. rubyが好き。本当はrubyでゲームプログラミングしたい ↩︎

  5. 未確認。後で試す ↩︎

Discussion