2017-05-13 21 views
0

我是Ocaml的新手,我對此代碼有問題(下文)。我正在嘗試編寫一個程序來對數組進行排序。我將數組分成兩部分,然後在這兩個數組上使用Array.sort(我將在後面解決這個問題,所以我不會使用Array.sort)。然後我想比較這兩個數組中的元素,但是我的代碼不工作。 有誰能告訴我問題在哪裏?代碼不工作:在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個循環屬於你的函數「合併」 –

回答

1

你的問題來自你對指令的誤解。讓我們試着去解釋它在一個簡單的和短期的方式:

  • 如果表達式返回一個值,它是一個表達式(bool,一個int,一個function ...)
  • 如果它不返回一個值(這意味着它有副作用),它是一個指令(我們說它返回unit,因爲實際上,這就是它的作用)。

當你有一個序列(這是一個接一個地執行多個指令是如何被調用的),你用;分隔它們。

因此,舉例來說,如果我寫這個

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

我有一個順序,我要與;分開我的指示。

如果我寫道:

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

你可以很容易明白,OCaml的不知道是哪裏的指令分離(是x := 1 print_int; !x或其他任何東西?)這就是爲什麼你需要;

現在問題出現在if

如果你寫

if cond then instr1; instr2 

什麼被解析爲

(if cond then instr1); instr2 

是,if cond then instr1是一個指令,因爲,它返回unit,不是嗎?因此instr2不在您的then區塊中。

但是,如果你寫

if cond then let e1 = e2 in instr1; instr2 

然後instr2then塊因施工let ... in創建其下的所有指令嵌套塊。

如果你已經從OCaml的,我的寶貴意見將是這樣的:總是在你conditionnalsbegin ... end。你會放心,你寫的是你認爲是解析的。

+0

比你的答案。 我的功能不再返回任何錯誤。但是當我調用函數(merge l r a ;;) 我得到這個: merge l r a ;; 錯誤:此表達式的類型爲int數組 ,但表達式類型爲(int ref - > int ref)array 類型int與類型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; 

的同時的前兩行循環也需要分號因爲它們也是語句塊。請注意,對於塊中的最後一條語句,您不需要分號。它們是分隔符,而不是語句結束。另外,作爲快捷方式,您可以使用incr i作爲i := !i + 1以及類似的語句。另外,千萬不要使用l或ll作爲變量名稱。 :-)

+0

每個模塊都不會有_need_圓括號或'begin ... end',但實際上從這個想法開始比較容易。 – Lhooq

+0

同時......是否需要開始和結束?或只是如果陳述? 我添加了開始到我的第一個if語句。我還添加了一些分號。 但現在其他字在下劃線,並且代碼不起作用。 我使用了這些變量的名字,所以我知道它們是什麼(左邊是左邊的長度) –

+0

不是。「do ... done」爲循環提供了類似的目的。請注意,在我的示例中,由於有'begin',所以'else'前面必須有'end'。 –