2017-09-22 17 views
1

私は絶対OCaml初心者です。私は文字を20回繰り返す関数を作りたいと思っています。 これは機能ですが、エラーのために機能しません。OCamlで文字列を繰り返す再帰関数

let string20 s = 
    let n = 20 in 
    s^string20 s (n - 1);; 

string20 "u";; 

私はこの

# string20 "u" 
- : string = "uuuuuuuuuuuuuuuuuuuu" 
+0

まず、再帰関数の停止条件について考える必要があります。次に、再帰関数を宣言するためにocamlに適用する構文を知っておく必要があります(これはコースのレベルです)。 –

+2

受け取っているエラーを入れてください。 – AlexKoren

+0

話題をはずしましたが、 'String.make 20 'は仕事をします。 – camlspotter

答えて

1

あなたの関数のように実行したいstring20、1つのパラメータを取りますが、あなたは、2つのパラメータで再帰的にそれを呼び出しています。

基本的な考え方はそこにありますが、正しい形式ではありません。続行する1つの方法は、2パラメータ関数を別の "ヘルパー"関数として分離することです。 @PierreGが指摘するように、ヘルパー関数を再帰関数としてdelcareする必要があります。あなたは一つのパラメータを取るためにあなたの関数を定義したが、あなたは再帰的に2で呼び出すようにしようとしているコメントで指摘したようにOCamlでは

0
  1. 再帰関数はlet rec
  2. で定義されています。

あなたは、おそらく「固定」部分および誘導部分に機能を分離するための一般的なパターンです

let rec stringn s n = 
    match n with 
    1 -> s 
| _ -> s^stringn s (n - 1) 
;; 
+0

Ocamlの関数はカレット化されているので、 'stringNの文字列Nを返すようなことができるので、' stringn'という名前はかなり冗長です。 "foo" ' – PieOhPah

+0

上記の関数は無限回帰です。決して減ることはありません。 – PieOhPah

+0

@ PieOhPah。ありがとう、私は(n - 1)を逃した。 –

0
let rec string n s = 
    if n = 0 then "" else s^string (n - 1) s 

let string20 = string 20 
0

ような何かをしたいです。この場合、入力文字列sを定数として修正したいので、新しい範囲で実際の再帰的な作業を行うにはネストされたヘルパー関数が必要です。したがって、s2に追加するために使用できます。 s2は、時間の経過とともに列列を構築するアキュムレータですが、cは、ベースケースに向かって1までカウントダウンするインダクタです。サイドノートでは

let rec repeat s n = 
    if n = 0 then "" else s^repeat s (n - 1) 

、最初と関数型言語についての1つの非常に楽しい事:あなたがすべてでヘルパー機能を必要としないので

let repeat s n = 
    let rec helper s1 n1 = 
    if n1 = 0 then s1 else helper (s1^s) (n1 - 1) 
    in helper "" n 

非末尾呼び出しのバージョンは、より簡単ですOcamlのような-class関数はcurrying(または部分的なアプリケーション)です。 n引数が標識された場合

# (* top-level *) 
# let repeat_foo = repeat "foo";; 
# repeat_foo 5;; 
- : bytes = "foofoofoofoofoo" (* top-level output *) 

:この場合、あなたは次のようにnまたはsのいずれかにそれを適用する上で、一部のようにタイプintとタイプstringsの二つの引数nを取るrepeatという名前の関数を作成することができます以下のように:

let rec repeat ?(n = 0) s = 
     if n = 0 then "" else s^repeat s (n - 1) 

アプリケーションの順序は、機能をより柔軟になって、利用することができる。

# (* top-level *) 
# let repeat_10 = repeat ~n:10;; 
# repeat_10 "foo";; 
- : bytes = "foofoofoofoofoofoofoofoofoofoo" (* top-level output *) 

私の投稿Currying Exercise in JavaScript(これはJavaScriptですが、それに従うのはかなり簡単です)とこのlambda calculus primerを参照してください。

+0

実際に動作させるためには、あなたのtail-recursive 'helper'は基底の' s2'をより良く返し、 's'の代わりに' '' 'で呼び出すべきです。また、 's1'は冗長です。あなたの最後の例では '〜n'というラベルはどこから来ますか? –

+0

@AndreasRossbergはい訂正ありがとうございます。私はまた、分かりやすくするために、ラベル付き引数バージョンを追加しました。 – PieOhPah

+0

私は「ヘルパー」への呼び出しがまだ間違っていると信じています。空の文字列で呼び出す必要があります。 –

関連する問題