Diksamの関数型

Diksamの構文規則において、関数呼び出しは以下のようになっています。

  primary_expression LP argument_list RP

つまり、式の後ろに、括弧で囲んだ引数並びを付け加えたものが関数呼び出しです(LP, RPはそれぞれleft paren, right parenで、「(」と「)」を意味します)。

これを、

  IDENTIFIER LP argument_list RP


としておけばいろいろ簡単だったのですが、わざわざ関数呼び出しを演算子としたのは、当然、Cで言うところの関数ポインタのようなものを実現したかったからです。

  dispatch_table[i](event);

のような呼び出しができれば、いろいろ便利ですよね。無名関数や、その場所でのローカル変数が見えるクロージャまで実現するつもりは今のところはありません。

こういうことをするのであれば、Diksamは静的型付け言語なので、「関数型」が必要になります。

「引数としてintを受け取り、戻り値としてdoubleを返す関数」を示す型の宣言として、まさかCのように

  double (*func)(int);

と書かせるわけにもいかず。

Javaはといえば、クロージャが導入されるという話を最初に聞いたころには、

  double(int) func;

と書かせることを想定していたようです。とはいえJavaは検査例外があるのでthrowsも書かねばならず、

  double(int) throws HogeException, PiyoException func;

と書くのかとか、いやこれでは文法に曖昧性が出るから

  double(int) throws HogeException | PiyoException func;

と書こうとか、いや実際にはこれも今は昔で現在はこんな案も出てたりとか、なんだかややこしいことになっているようです*1

当初、私はJava流の記法でよいかと思っていたのですが、

  double(int) func;

これだけでも初心者を戸惑わせるには十分ですし、throwsまで入ってきたら何をか言わんやです。

これならいっそ、C#流に、

  delegate double Func(int hoge);

のようにして型宣言だけしておく方がなんぼかマシに思えます。さてどうしたものか*2

ところで、Diksamの実装のほうは、現在こんな感じです。

  • 組み込みライブラリとしてfopen(), fgets(), fputs(), fclose()をサポートしました。
  • finalによる定数をサポートしました。
  • switch caseをサポートしました。
  • do whileを現在実装中……

switch caseですが、CやJavaのfall throughな仕様はいくらなんでも許しがたいですし、C#のように見た目は似ていて動きが違うのもどうかと思いますので、以下のようにしました。

  switch (a)
  case 1 {
      // aが1の時に実行
  } case 2, 3 {
      // aが2または3の時に実行
  } case 4 {
      // aが4の時に実行
  } default {
      // aが1でも2でも3でも4でもないときに実行。
  }

あまり美しくない気もしますが……

なお、Diksamのswitch caseは、switchの式(上記ならa)と、caseの式が==で比較できれば原則使用可能です(==で発生する型変換が起きないという違いはありますが)。よって、文字列等による分岐も可能です。

*1:最新情報を追えていないので詳しい方はツッコミ願います

*2:C#流にするとして、delegate型の宣言は、クラス宣言と同列にもってくるつもりです。enumも持ってくるならそこかなあ。