C到OCaml-如果条件在for循环OCaml中

时间:2018-10-21 12:52:26

标签: c ocaml

我正在尝试将C代码重写为OCaml。但是,我不确定如何在OCaml的for循环内处理多个if条件。您能帮我弄清楚该怎么做吗? 我有C代码,也有在OCaml中所做的事情,这是行不通的。

C代码:

bool function1 (int x, int y, int movei, int sol[][], int xMove[], int yMove[], int n) 
{ 
    int i, next_x, next_y; 
    if (movei == n) 
        return true; 

    for (i = 0; i < n; i++) { 
        next_x = x + xMove[i]; 
        next_y = y + yMove[i]; 

        if (function2(next_x, next_y, sol)) { 
            sol[next_x][next_y] = movei; 

            if (function1(next_x, next_y, movei + 1, sol, xMove, yMove, n)) 
                return true; 
            else
                sol[next_x][next_y] = 0;
        } 
    } 

    return false; 
}

编辑:OCaml代码

我已经基于glennsl答案更改了OCaml代码,但是编译器抱怨'('和')'的匹配和预期不足。

let rec function1 x y movei sol xMove yMove n =
if movei=n then true
else
    (
    for i=0 to n-1 do 
    (
        let next_x = x + xMove.(i) in
        let next_y = y + yMove.(i) in

            if (function2 next_x next_y sol) then 
            sol.(next_x).(next_y)<-movei in 
                (
                    if (function1 next_x next_y movei+1 sol xMove yMove n) then true
                    else sol.(next_x).(next_y)<-0
                )   
            else false  

    done;; )
)

以前的OCaml代码:

let rec function1 x y movei sol xMove yMove n =
if movei=n then true
else
    for i=0 to n-1 do
        let next_x = x + xMove.(i);
        let next_y = y + yMove.(i);

            if (function2 next_x next_y sol) then
                sol.(next_x).(next_y)<-movei;

                    if (function1 next_x next_y movei+1 sol xMove yMove n) then true
                    else sol.(next_x).(next_y)<-0

            else ()

    done;;

编译器在OCaml代码的最后一行说“语法错误”,其中 ;; 是。

2 个答案:

答案 0 :(得分:3)

您的代码有几个问题:

  1. 您遇到的语法错误是由于第一个else被解释为属于第一个if,而第二个else悬而未决。 OCaml对缩进不敏感,因此您需要用括号或beginend将嵌套的控制结构括在括号内,它们与括号完全相同,但在分隔代码块时看起来更好。最好使用ocp-indent自动以解释方式缩进代码,这具有揭示此类错误的良好副作用。

  2. let x = y仅是顶级声明,分号不是语句终止符,而是链接表达式并丢弃第一个结果的运算符。 OCaml是一种基于表达式的语言,虽然它确实支持命令式编程,但是它没有语句。您要使用的是let x = y in z,它将y的计算结果绑定到表达式x中的名称z。只需将let之后的分号替换为in,即可使用。

  3. 您的if表达式的分支返回不同的值。大多数返回unit,但其中两个返回bool,这是类型错误,因为该函数或任何其他表达式不能同时返回unitbool 。从C代码看来,无论您现在正返回false的何处,都应该隐式地(如果表达式的计算结果为())或显式地返回()

  4. OCaml也不使用空格进行分组,因此function1 next_x next_y movei+1 sol xMove yMove n不会像您期望的那样被解释,而是被解释为(function1 next_x next_y movei) + (1 sol xMove yMove n),因为函数应用程序的优先级高于+运算符。将move+1括在括号内,以使其成为function1的单个参数。

答案 1 :(得分:1)

此示例中的问题是“返回true;”实际上会中止for循环和整个递归。

在ocaml的命令式代码中反映这种流的一种方法是使用异常。因此所有Date ... 2017-01-01 00:00:00 ... 2017-01-01 01:00:00 ... 2017-01-01 02:00:00 ... 2017-01-01 03:00:00 ... 2017-01-01 04:00:00 ... 都将变成return true;。只需删除raise Found,函数就会返回一个单位值。

然后添加第二个功能

return false;

恢复原始API。