公式フォーラムを眺めていたら、Verse本の修正が必要な事象に出会いました。「比較の戻り値」についてです。
一般的な言語では、比較式は真偽型(true/false)を返します。
しかし、Verseでは比較式は「左辺の値」を返します。
……マジかよ!!! 公式ドキュメントに載ってないよそんな言語仕様!(土屋調べ。誰か見つけたら教えてください)
下記を見て下さい。
FuncA()<transacts><decides>:void = 1 > 0 #問題無し FuncB()<transacts><decides>:logic = 1 > 0 #コンパイルエラー! FuncC()<transacts><decides>:int = 1 > 0 #問題無し
関数では最後に評価された式が戻り値になります。<decides>
エフェクトが指定された関数は、コードブロック内に失敗許容式(ここでは比較式)が記述できます。比較式1>0
は常に成功します。
FuncA[]
/FuncB[]
/FuncC[]
の違いは戻り値の型のみです。そして、これらの関数の中でFuncA2[]
のみがコンパイルエラーになっているのが分かります。
コンパイルエラーは2箇所発生しています。一つ目はこちら。
Function `FuncB` returns `logic` and can also fail. This combination is not allowed for semantic clarity.(3542) FuncB関数はlogicを返し、かつ失敗可能です。意味を明確する必要があるため、この組み合わせは許可されません。
「logic型を返す失敗許容関数は作成出来ない」という恐ろしい事が書かれています。え、そうだったの!?(これについては後述します)
二つ目のコンパイルエラーはこちら。こっちが本命です。
This function returns a value of type logic, but the function body's result is an incompatible value of type int.(3510) この関数はlogic型を返します。しかし、関数のボディの結果(result)は互換性の無い値であるint型です。
result
は関数が返す値の事で、ここでは1>0
の評価結果であり、それはint
型だと言われています。
つまり、比較式1>0
はint
型を返すので、関数の戻り値の型もint
型(あるいはvoid
型)でなければならないわけですね。
最後に、比較式の左辺が戻り値である事も確認しておきます。
hello_world_device := class(creative_device): #常に成功する失敗許容関数 Success()<transacts><decides>:int = 1 > 0 OnBegin<override>()<suspends>:void= if: Result := Success[] then: Print("number = {Result}") #LogVerse: : number = 1
出力結果は1
でした。比較式が評価されると左辺を返すというのは正しいようです(ドキュメントには書いてありませんが)。
何故比較式が真偽値を返さないのか。
何故Verseでは比較式が(他のプログラミング言語のように)真偽値を返さないのかを少し考えてみます。そもそもドキュメントに記載が無い言語仕様のため想像しかできませんが、考えてみるとこれは優れた設計に思えました。
Verseの比較式は常に失敗許容式であり、式が成立しない場合は失敗します。もし比較式が式の成立/不成立に応じて真偽値を返す場合、比較式はどんな時でもtrueだけを返すことになります。何故なら、式が不成立の場合、falseを返す事無く失敗するからです。
これでは比較式の戻り値に意味が無くなり、もったいありません。logic型が戻り値になる失敗許容関数が許されないのも、これに起因するのだと思われます。
代わりに、式の結果として右辺か左辺のどちらか(等価式の場合を考えると左辺が変える方が自然)を返すようにすれば、式をメソッドチェーンに接続できるので使い勝手が良いです(多分)。
というわけで、まさかこんな仕様になっていると思っておらず、Verse本では間違った説明になっています。電子版については近いうちに修正します。恥ずかしい!><
宣伝
Verse言語の言語仕様解説同人誌をPDFで頒布しています。よろしければどうぞ。