2

int nを受け入れ、nから0まで実行されるリストを返す関数を作成しようとしています。

これは私が持っているものです

let rec downFrom n =
let m = n+1 in
if m = 0 then                                                                                  
  []                                                                                           
else                                                                                            
  (m-1) :: downFrom (m - 1);;

関数は正常にコンパイルされますが、intを使用してテストすると、評価中にスタックオーバーフローエラーが発生します(ループ再帰?)。

邪魔になるのは地元の変数だと知っていますが、それを宣言する別の方法はわかりません。ありがとうございました!!!

4

3 に答える 3

3

まず、プログラムの本当の問題は、無限ループがあることです。なぜ、あなたの帰納的基本ケースは0であるが、あなたは常にn!これは、あなたm - 1が本当にどちらに再帰するかのためですn + 1 - 1

rec再帰関数で必要なキーワードが含まれていないので、なぜこれがコンパイルされるのか驚いています。OCamlでのスタックオーバーフローを回避するには、通常、次のような末尾再帰スタイルに切り替えます。

let downFrom n =
  let rec h n acc = 
    if n = 0 then List.rev acc else h (n-1) (n::acc)
  in
  h n []

誰かが次の編集を提案しました:

let downFrom n =
    let rec h m acc =
        if m > n then acc else h (m + 1) (m::acc)
    in
    h 0 [];

これにより、List.revへの呼び出しが節約されます。同意します。

于 2012-09-19T21:54:15.667 に答える
1

再帰の鍵は、再帰呼び出しは問題のより小さなバージョンでなければならないということです。再帰呼び出しによって、問題の小さなバージョンが作成されることはありません。同じ問題を繰り返すだけです。

于 2012-09-19T21:55:21.463 に答える
0

フィルタリングパラメータの構文を試すことができます。

let f = function
   p1 -> expr1
 | p2 -> expr2
 | p3 -> ...;;

let rec n_to_one =function
  0->[]
  |n->n::n_to_one (n-1);;

# n_to_one 3;;
- : int list = [3; 2; 1]
于 2013-01-05T16:10:47.277 に答える