简体   繁体   中英

C to OCaml - If conditions inside a for loop OCaml

I'm trying to rewrite a C code into OCaml. However, I'm not sure how to work with multiple if conditions inside a for loop in OCaml. Can you help me figure out how to do that? I have the C code and what I've done in OCaml, which isn't working.

C code:

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

EDIT: OCaml code

I've changed my OCaml code based on glennsl answer, but the compiler complains about '(' and ')' being unmatched and expected.

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

Previous OCaml code:

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

The compiler says "Syntax error" in the last line of the OCaml code, where the done;; is.

There are several problems with your code:

  1. The syntax error you're getting is caused by the first else being interpreted as belonging to the first if , leaving the second else dangling. OCaml is not indentation sensitive, so you need to surround nested control structures with parentheses or begin and end , which are exactly the same as parentheses but look better when delimiting blocks of code. It's a good idea to use ocp-indent to automatically indent your code the way it'll be interpreted, which has the nice side-effect of revealing errors like this.

  2. let x = y is a top-level declaration only and semicolon is not a statement terminator but an operator that chains expressions and throws away the result of the first. OCaml is an expression-based language, and while it does support imperative programming it does not have statements. What you want to use instead is let x = y in z , which binds the result of evaluating y to the name x in the expression z . Just replace the semicolons after the let s with in , then it'll work.

  3. The branches of your if -expressions return different values. Most return unit , but two of them return a bool , which is a type error since the function, or any other expression, can't return both unit and bool . From the C code it looks like you should return false wherever you're now returning () , implicitly (if the expression evaluates to () ) or explicitly.

  4. OCaml also does not use whitespace for grouping, and so function1 next_x next_y movei+1 sol xMove yMove n will not be interpreted as you expect, but rather as (function1 next_x next_y movei) + (1 sol xMove yMove n) due to the precedence of function application being higher than that of the + operator. Surround move+1 in parentheses to make it a single argument to function1 .

The problem in this example is the "return true;" that aborts the for loop and the whole recursion actually.

One way to mirror that kind of flow in imperative code in ocaml is to use an exception. So all return true; would become raise Found . The return false; is simply removed and the function returns a unit value.

You then add a second function that does

let function1 x y movei sol xMove yMove n =
    try
        function1 x y movei sol xMove yMove n;
        false
    with Found -> true

to restore the original API.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM