13

私は最近OCamlを勉強していて、これに出くわしました:

OCaml は let rec の右側に置くことができるものに制限があります。このように

let memo_rec f_norec =
let rec f = memoize (fun x -> f_norec f x) in
f;; 
Error: This kind of expression is not allowed as right-hand side of `let rec'

memoize は、関数を取り、Hashtable を使用して記憶されたバージョンに変換する関数です。OCaml では 'let rec' の右側の構文の使用に何らかの制限があることは明らかですが、私にはよくわかりません。誰かこれについてもう少し説明してもらえますか?

4

2 に答える 2

11

バインドできる式の種類は、マニュアルのセクション 8.1let recに記載されています。具体的には、定義された名前を含む関数の適用は許可されていません。let rec

大まかな要約(そのリンクから取得):

非形式的には、受け入れられた定義のクラスは、定義された名前が関数本体内またはデータ コンストラクターへの引数としてのみ発生する定義で構成されます。

于 2013-11-08T13:43:54.240 に答える
8

結び目を結ぶ手法を使用して、メモ化の修正点を定義できます。たとえば、次の 2 つの同等の定義を参照してください。

let fix_memo f =
  let rec g = {contents = fixpoint}
  and fixpoint x = f !g x in
  g := memoize !g;
  !g

let fix_memo f =
  let g = ref (fun _ -> assert false) in
  g := memoize (fun x -> f !g x);
  !g

またはlazy、アランが思い出したように使用します:

let fix_memo f =
  let rec fix = lazy (memoize (fun x -> f (Lazy.force fix) x)) in
  Lazy.force fix
于 2013-11-08T19:28:57.007 に答える