2017-05-13 25 views
0

私はOcamlを初めて使用しています。このコードには以下の問題があります。配列をソートするプログラムを作成しようとしています。私は2つのハーフに配列を分割し、それらの2つの配列でArray.sortを使用しました(私は後でそれを修正しようとしていますので、Array.sortは使用しません)。そして、私はそれらの2つの配列の要素を比較したいと思いましたが、コードが機能していません。 誰が問題がどこにあるか教えていただけますか?コードが機能しません:ocamlで配列をソート

let a =[|5;4;2;6;1;3|] ;; 
let n = Array.length a;; 


let l= Array.sub a 0 (n/2);; 
Array.sort compare l;; 
l;; 
let ll= Array.length l;; 


let r= Array.sub a (n/2) (n/2);; 
Array.sort compare r;; 
r;; 
let lr=Array.length r;; 

let merge l r a = 
    let k =ref 0 in 
    let i = ref 0 in 
    let j =ref 0 in 

while(!i<ll && !j< lr) do 
     if(l.(!i) <= r.(!j)) then 
       a.(!k) <- l.(!i) 
       i:= !i+1 
     else begin 
       a.(!k) <- r.(!j) 
       j:= !j+1; 
       k:= !k+1 
     end; 

while (!i<ll) do 
     a.(!k)<-l.(!i) 
     i:= !i+1; 
     k:=!k+1; 
done; 

while (!j<ll) do 
     a.(!k) <-r.(!j) 
     j:= !j+1; 
     k:= !k+1 
done; 
done;; 

merge l r a;; 
+0

ありがとうございます!今年のこの時期に、誰もが "もし...、始まり...終わりに!" – Lhooq

+1

だから、あなたのコードを操作して、emacsのtuaregや自動インデントを行うものをインデントして、必要に応じて ';'と 'begin ... end'を追加してください。 – Lhooq

+0

完全にLhooqに同意します。さらに、いくつかの ";;"最後の2つのループはあなたの関数 "merge"に属しています。 –

答えて

1

あなたの問題は、どのような指示が誤解されているかによって生じます。のは、簡単で短い方法でそれを説明してみましょう:

  • あなたの式が値を返す場合、それは表現だ(boolintfunction ...)
  • それは返さない場合値(副作用を意味する)、それは命令です(実際にはそれがしているので、unitを返します)。

シーケンス(複数の命令が次々に実行される方法)を使用するときは、;でそれらを区切ります。私はこの

let f x = x := 1; print_int !x; print_newline() 

を書く場合

ので、例えば、私は順序があると私は;と私の指示を分離する必要があります。私が書いた場合

:あなたは簡単に命令が分離されているOCamlは知ることができないことを理解することができます

let f x = x := 1 print_int !x print_newline() 

あなたが;を必要とする理由です(??それx := 1 print_int; !xそれとも何か他のものがあります)。

今やifで問題が発生します。まあ、それはunit返す、ため

あなたが解析され、どのような

if cond then instr1; instr2 

(if cond then instr1); instr2 

Yesで書く場合は、if cond then instr1はありません、命令ですか?だからinstr2はあなたのthenブロックに含まれていません。

しかし、あなたは

if cond then let e1 = e2 in instr1; instr2 

を書く場合の建設let ... inは、すべての命令がネストされているその下のブロックを作成するため、次にinstr2thenブロックです。

あなたはOCamlで始まるしている場合は、私の貴重なアドバイスは、このようになります:は常にあなたのconditionnalsbegin ... endを書きます。あなたが書いていることは、あなたが思っていると思うものであると確信できます。

+0

あなたの答えよりも。 私の関数はもうエラーを返しません。しかし、関数を呼び出すと(merge l r a ;;) 私はこれを得ます: merge l r a ;; エラー:この式はint型の配列 ですが、型(int ref - > int ref)の配列が必要です int型はint型と互換性がありませんref - > int ref –

+0

マージ関数のシグネチャは何ですか? (あなたはトップレベルの環境で簡単にそれを得ることができます) –

+0

私は自分のコードを修正しましたので、今は働いています。 –

1

私はコメントするにはあまりにも新しいですが、すべてのブロックがいずれかの必要()またはbegin ... endを括弧ことを指摘します。したがって、最初のifステートメントは、行の最後にthen beginとする必要があります。 beginelseのようにそれらを分離するためにセミコロンが必要との間のステートメント:彼らはまた、文のブロックであるので

if(l.(!i) <= r.(!j)) then begin 
    a.(!k) <- l.(!i); 
    i:= !i+1 
end else begin 
    a.(!k) <- r.(!j); 
    j := !j+1; 
    k:= !k+1 
end; 

は、whileループの最初の2行はまた、セミコロンを必要とします。ブロック内の最後のステートメントにセミコロンは必要ないことに注意してください。それらはセパレータであり、ステートメントの終わりではありません。また、ショートカットとしてi := !i + 1などの文にはincr iを使用できます。また、変数名としてlまたはllを使用しないでください。 :-)

+0

すべてのブロックは括弧や 'begin ... end'を必要としませんが、実際にこの考え方から始める方が簡単です。 – Lhooq

+0

また、While ... do ...開始と終了が必要ですか?または単に文をif文ですか? 私は最初のif文にbeginを追加しました。私はセミコロンもいくつか追加しました。 しかし、ここでは下線のelseがあり、コードは機能していません。 私はそれらの変数名を使用していましたので、私はそれらが何であるかを知っています(左側のl-左の長さ) –

+0

いいえ 'do ... done'はループの目的に似ています。私の例では、 'begin'があるので' else'の前に 'end'がなければならないことに注意してください。 –

関連する問題