このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

void型とunit型とoneway呼び出し

void型とunit型に関して、だいぶ前に話題にしたことがあります。

void型は、直感的には「値がない」ことを示します。unit型(シングルトン型ともいいます)は、常に特定・単一の値を返すことを示します。

多くの場合、void型はunit型だと解釈できますが、それとは対極的な解釈として「void型はany型だ」というのもあります。戻り値がvoid型だと宣言された関数は、どんな値を返すかわからない。どんな値でも返す可能性がある。だから、そんな当てにならない値を使ってはいけない、捨てろ! という解釈ですね。

いずれにしても、voidには「実は値がある」という解釈です。でも、ほんとに値がないケースが2種類あります。1つ目は常に例外を起こして正常な戻り値を返さない関数*1です。

void error_exit(string message);

絶対に値を返さないことを明示したいなら、voidよりneverとでも書いた方がいいでしょう。(下の宣言の構文はテケトー。)

never error_exit(string message) throws SomeRuntimeException;

絶対に値を返さない別なケースは一方向のリモート呼び出しです。

oneway void notifyWeather(weather w);

oneway void という書き方は実際にIDL(Interface Definition/Description Language)で使われます。リモート呼び出しのときに戻り値があるなら、呼び出し要求を発行した後で戻り値の到着を待ちます。しかし、oneway void が指定されると送りっぱなしにします。呼び出しというよりは単なる送出で、「関数/手続き呼び出し」よりは「イベント配送」のセマンティクスになります。

さて、void型戻り値の解釈として、unit型、any型、oneway void型がありますが、これらの違いを理解するには状態遷移で考えた方がいいでしょう。関数呼び出しの戻り値を入れるレジスタがあって、そのレジスタ値が呼び出し後にどう変化するかを考えてみます。

  1. いつでも特定の値にセットされるなら、unit型
  2. どんな値に書き換えられるかまったく予測できないなら、any型
  3. 直前の値のまま(そもそも書き換えが起きない)なら、oneway void型

*1:「そんなのは関数と呼ばない」って意見もあるでしょうが、割とみんな関数と呼んでるようですから、、、