Section 2. 構文

2.1 変数宣言

グローバル変数やローカル変数を宣言します。

let val d = (* グローバル宣言; ここより後で変数gを使用できる *)
  test[1]

let val d = (* グローバル宣言; ここより前の変数gが隠蔽される *)
  let val d = test[2] in (* ローカル宣言; この部分だけで使用できる *)
    d

2.2 条件分岐

条件式を評価し、真の場合前者を、偽の場合後者を選択して実行します。偽の場合に選択される実行文を省略できません。

let _ = if 1 = 2 then "Yes" else "No"

2.3 関数宣言

関数を宣言します。型を省略できません。

fun add (Int as da) (Int as db) : Int = 
  da + db
  (* Int型の引数daとdbの和を返す関数定義; 任意の場所で使用できる *)

let val d = add(1)(2)
  (* 3を得る *)

type t = ty X
fun label {{X}} (t as d) : test[t] =
  test[d]
  (* X型の引数にラベルtestを付ける関数定義
     型変数を明記しなければならない *)

let val d = label(1)
  (* test[1]を得る *)

2.4 パターンマッチ

パターンのうち初めてマッチしたところを実行します。

fun sum (Int* as d) : Int =
  match d with
    () -> 0
  | (Int as a, Int* as b)
      -> a + sum(b)
  }
  (* 引数の和を返す *)

すべての値に対しいずれかのパターンがマッチしなければなりません。この検査は、既に述べた網羅性検査に当たります。加えて、すべてのパターンに対しマッチする値がなければなりません。この検査は、非冗長性検査と言います。

2.5 例外

例外が発生させると、例外を捕捉する一番内側のパターンのうち初めてマッチしたところを実行します。パターンにマッチしなければ、一個外側のパターンに対して同様の操作を繰り返します。

fun mkdir (String as dirname): () = 
  try
    if (system("mkdir", dirname) = 0) then
      ()
    else
      raise("cannot mkdir")
  (* ディレクトリを作成する。できなければ、例外を発生させる *)

let val _ =
  try mkdir("foo") with
    AnyElms as msg -> print(msg)
  (* 例外を捕捉すると、メッセージを印字する *)

ただし、XDuce 0.5.0はパーサに致命的な不具合があり、例外の捕捉は動作しません。

2.6 フィルタ

正規表現型においては、従来の型よりも、より高度なパターンマッチが求められます。例えば、反復のうちで値を変数に代入して処理したい、選択のどちらかで値を変数に代入して処理したいなどの要請があります。パターンマッチでは、パターンと処理が完全に分離しているので、対応できません。XDuceでは、パターンと処理を混在させた新しい構文として、フィルタ構文が提案されています。

fun sum (Int* as d) : Int =
  filter d {
    () { 0 }
  | (Int as a, Int* as b) { a + sum(b) }
  }
  (* 引数の和を返す *)

let val d = add(1, 2, 3)
  (* 6を得る *)

fun labeleach (Int* as d) : test[Int]* =
  filter d {
    ( (Int as d) { test[d] } )*
  }
  (* 各引数にラベルtestを付ける関数定義;
     フィルタ構文には型変数の使用はできない *)

let val d = label(1, 2, 3)
  (* test[1], test[2], test[3]を得る *)

パターンマッチとは処理方法が違うので、初めてマッチしたところが実行されるとは限りません。幾つかにマッチした場合は、どれが実行されるかは不定です。

平野貴仁 hiranotaka%zng.info