代码不起作用:在ocaml中排序数组

时间:2017-05-13 14:50:14

标签: arrays sorting ocaml

我是Ocaml的新手,我对此代码有疑问(如下)。我正在尝试编写一个程序来排序数组。我将数组分成两半,然后我在这两个数组上使用了Array.sort(我稍后会修复它,所以我不会使用Array.sort)。然后我想比较这两个数组中的元素,但我的代码不起作用。 谁能告诉我问题出在哪里?

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;;

2 个答案:

答案 0 :(得分:1)

我太新了评论,但会指出每个块都需要括号()begin ... end。因此,您的第一个if语句应该在行尾有then beginbeginelse之间的陈述需要使用分号来区分它们,如下所示:

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循环的前两行也需要分号,因为它们也是一个语句块。请注意,块中的最后一个语句不需要使用分号。它们是分隔符,而不是结束语。此外,作为快捷方式,您可以将incr i用于i := !i + 1和类似语句。此外,永远不要使用l或ll作为变量名。 : - )

答案 1 :(得分:1)

您的问题来自您对指令的误解。让我们尝试以简单明了的方式解释它:

  • 如果您的表达式返回值,则表达式为boolintfunction ...)
  • 如果它没有返回一个值(这意味着它会产生副作用),它就是一条指令(我们说它返回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

然后instr2位于then块中,因为构造let ... in创建了一个块,所有指令都嵌套在该块中。

如果您从OCaml开始,我的宝贵建议是: 始终在您的条件中写begin ... end 。你可以放心,你所写的就是你认为被解析的东西。