7.3 値の再帰的定義 (Recursive definitions of values)

[[6.7.1節>6.7 Expressions#content_1_0]]で言及したように、let rec 束縛構文は 再帰関数と同様に、 関数以外のクラスの再帰的定義もサポートします。 例えば:

       let rec name_1 = 1 ::  name_2 and  name_2 = 2 ::  name_1 in  expr 

これは name_1 を循環的なリスト 1::2::1::1::... に、 name_2 を循環的なリスト 2::1::2::1::... に束縛します。 非形式的には、 可能な定義のクラスは 定義されている名前が関数本体の内部かデータ構築子(FIXME:data constructor)の引数としてのみ出現するような定義から構成されます。

より精確には、 次の式を考えてみてください:

        let rec name_1 =  expr_1 and ... and  name_n =  expr_n in  expr 

これは 各 expr_1 ... expr_n が name_1 ... name_n に関して静的に構築でき 直接 name_1 ... name_n に直接リンクされていない場合に許可されます。

「式 e が name_1 ... name_n に関して静的に構築できる」とは、 少なくとも次のいずれかの条件のうちひとつが真となる場合です: - e に どの name_1 ... name_n も自由に出現していない - e は変数である - e は fun ... -> ... の形である - e は function ... -> ... の形である - e は lazy ( ... ) の形である - e は 次のうちどれか一つの形である ここで expr_1 ... expr_m はそれぞれ name_1 ... name_n に関して静的に構築でき、 expr_0 は name_1 ... name_n に関して静的に構築でき、 xname_1 ... xname_m は次の形である: -- let [rec] xname_1 = expr_1 and ... and xname_m = expr_m in expr_0 -- let module ... in expr_1 -- constr ( expr_1, ... , expr_m) -- `tag-name ( expr_1, ... , expr_m) -- [| expr_1; ... ; expr_m |] -- { field_1 = expr_1; ... ; field_m = expr_m } -- { expr_1 with field_2 = expr_2; ... ; field_m = expr_m } ここで expr_1 は name_1 ... name_n に直接リンクされていないこと -- ( expr_1, ... , expr_m ) -- expr_1; ... ; expr_m

式 e は 次の場合に 変数 に直接リンクされていると言います: - e は 名前である - e は expr_1; ... ; expr_m の形で、 expr_m が 名前に直接リンクされている - e は let [rec] xname_1 = expr_1 and ... and xname_m = expr_m in expr_0 の形である ここで expr_0 は xname_i (expr_i が名前に直接リンクされている) のどれかに直接リンクされているとき name