2017-05-13 19 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'。 –