我正在尝试将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代码的最后一行说“语法错误”,其中 ;; 是。
答案 0 :(得分:3)
您的代码有几个问题:
您遇到的语法错误是由于第一个else
被解释为属于第一个if
,而第二个else
悬而未决。 OCaml对缩进不敏感,因此您需要用括号或begin
和end
将嵌套的控制结构括在括号内,它们与括号完全相同,但在分隔代码块时看起来更好。最好使用ocp-indent
自动以解释方式缩进代码,这具有揭示此类错误的良好副作用。
let x = y
仅是顶级声明,分号不是语句终止符,而是链接表达式并丢弃第一个结果的运算符。 OCaml是一种基于表达式的语言,虽然它确实支持命令式编程,但是它没有语句。您要使用的是let x = y in z
,它将y
的计算结果绑定到表达式x
中的名称z
。只需将let
之后的分号替换为in
,即可使用。
您的if
表达式的分支返回不同的值。大多数返回unit
,但其中两个返回bool
,这是类型错误,因为该函数或任何其他表达式不能同时返回unit
和bool
。从C代码看来,无论您现在正返回false
的何处,都应该隐式地(如果表达式的计算结果为()
)或显式地返回()
。
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。