😽

[UEFN]verse言語の設計思想を読み解きたい(1) 定数定義/変数定義

2023/03/30に公開

verse言語について

先週だか先々週だかにフォートナイト用の記述言語こと(「メタバース記述言語」と書くのは個人的に抵抗があります)「verse」が開発環境「UEFN(Unreal Engiine for Fortnite)」と共にリリースされました。
https://dev.epicgames.com/documentation/ja-jp/uefn/verse-language-reference
 Haskell言語の開発者の1人がEpicに移籍して開発に関わっているverse言語は、ドキュメントを読む限り、並列処理およびトランザクション処理の対応を言語仕様レベルで取り組み、またそれによってゲームプログラミング(ここではメタバースを含む)特有の課題を解決しようとしている、非常にチャレンジングな言語に見えて、興味が尽きません。

とはいえ、そのせいもあってなのか、verseは独特な記法のプログラミング言語になっていて、初学時のハードルが高いように感じます。また、ruby/C#に慣れている土屋にとって、haskell系(という感じでもないし)関数型言語(という感じでもないんだけど)の文法規則にさっぱり慣れません(これは確かにそんな感じ)。

そんなわけで、ここではverse言語のとっつきにくい文法とその意味について、主にC#やrubyと比較しながら見ていこうと思います。
 勉強の最中に気づいた事をメモしていくくらいのつもりで、間違いも平気で書いていくかと思います。まだ実行環境を用意してないので暫くは間違いまくってるかも。なので、適宜コメントなどで指摘していただけると嬉しいです(本文に修正できるかはわからないけど、コメントも含めて記事ということでご了承ください)。

不定期かつ思いついた順に書くので、順番はバラバラです。後で再編集するかもしれないしないかもしれない。

定数と変数

今回は定数定義と変数定義について
https://dev.epicgames.com/documentation/ja-jp/uefn/variables-in-verse

定数定義

verseでの定数宣言はこんな感じ。

#Int型定数CharIDを0で初期化
CharID : Int = 0

C#では定数の場合、通常の変数宣言にconstを付与する事で定数を示しますが、verseでは何も付与されていない場合に定数になります。
 "#"で始まる行はコメントです(rubyライクで素敵)。型の指定は":"を介して後置。式の終わりに";"などのデリミタは必要ありません。
 今、「式」と書きましたが、verseのコードは全て「式(expression)」で構成されていて、「文(statement)」はありません(多分)。ifやloopも式です。
 ローカル(非グローバルスコープぐらいの意味だと思われる)における定数宣言では、以下の様に型の記述を省略できます(型推論されます)。

#Int型定数CharIDを0で初期化
CharID := 0

サンプルコードを観ていると、この":="という表記がよく出て来ますが、型を省略しているだけで、verseに「:=演算子」は無いです(無い筈。……合ってる?)。

なぜローカルでしか型を省略できないのかというと、ファイルスコープ(こんな用語ないけどひとまず)に配置された定数はモジュールのインターフェイスとして外部から参照される役割を持つので、型情報の明示が必要なのかなと思います。
 モジュールというのは、ファイル単位(実際にはフォルダ単位)でコードを外部から参照できる仕組みです。ただし、公開するインターフェイスは制限出来る筈で、じゃあ公開しない定数は型省略できてもいいじゃないかという気はします(この辺ちゃんと見て無いので曖昧)。

変数定義

一方変数宣言はこんな感じ。

#Int型変数CharInstanceNoを0で初期化
var CharInstanceNo : Int = 0

変数定義には"var"を付与します。変数の場合は初期化("= 0")を省略できます(省略しない事が推奨されています)。変数では型を省略できません(出来ても良さそうなもんだけど)。
 また、変数の更新には"set"による明示が必要です。

set X = 1
set X += 1

"set +="は「代入割り当て(Addition assignment)」演算子、"set ="は「変数割り当て(Variable assignment)」演算子です。ちなみに言うとverseでは、"="は代入演算子ではなく等価演算子です。

「変数の更新」という頻出処理に毎回"set"を付けるのは煩雑に思えますが、「値とは基本的にstaicな物で、更新する場合にはそれを明確にする」というのは、関数型言語を含め最近のスタイルと言えます(こんな雑に書いたら関数型言語の形をしたマサカリが飛んでくるかもしれないけど)。

これは土屋の想像ですが、verseは「事故らないこと、止まらないこと」を重視している言語で、その為に安全な処理(例えば定数の設定)とそうで無い処理(例えば変数の更新)との違いを、文法レベルで区別し、安全では無い処理を例外フロー側に寄せているのかなと思います。

余談ですが、先述したようにverseでは"="は比較演算子ではなく等価演算子です(verseには"=="演算子がありません)。なので、もし"X=1"と書くとそれは論理式になってしまいます。ただし、verseでは論理式の扱いが他の言語と比べて特殊で、論理式を記述出来る場所が強く制限されているので、そんなには混乱しないと思います(間違えて"=="と書いてしまう混乱は永遠に続きそうですが……)。
 「論理式の扱いが特殊」というのはverseのキモの1つで、これも「事故らないこと、止まらないこと」に通じる仕様です(if式のパートで書くと思われる)。

クラスフィールド(クラスの変数定義)

https://dev.epicgames.com/documentation/ja-jp/uefn/class-in-verse
 クラスのメンバ変数は「フィールド」と呼ばれます。フィールドの定義にもvarの有り/無しがあります。

cat := class:
    Name : string
    var Age : int = 0

Nameはアーキタイプ(C#で言うオブジェクト初期化子)で値を設定すると、以降は不変(immutable)に振る舞います(C#で言うreadonly)。Ageは変数として振る舞います。フィールドの定義では初期化は必須ではありません(合っても無くても良い)。

終わりに

ひとまず今回はこのくらいで。定数定義/変数定義だけでも、C系とは随分と勝手の違う言語だということが分かるかと思います。verseは(土屋の説明が本当に合っているのかも含めて)まだわからない事だらけですが、弄り甲斐はありそうなので、今後もちょこちょこ触っていきたいと思います。

補足

念のため書いて置きますが「事故らないこと、止まらないこと」は土屋が想像で書いているだけで、verseのスローガンとかではまったくありません。

続き

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


お知らせ

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

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

#Verse #UEFN #Fortnite #Verselang #UnrealEngine

宣伝

「Unityシェーダープログラミングの教科書」シリーズ1~5をBOOTHで頒布中です。
https://s-games.booth.pm/

Discussion