Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Break" for loop in OCaml

I need to test all possible combinations in a 5 element array in OCaml, if any combination meets a condition, I must stop for loops and return that array, but is not easy return something in a for...

I have this code:

let myfunction t =
 let arraycolours = Array.make 5 W in
  try
   for i=0 to 3 do
    Array.set arraycolours 0 (inttocolour i);
    for j=0 to 3 do
     Array.set arraycolours 1 (inttocolour j);
     for k=0 to 3 do
      Array.set arraycolours 2 (inttocolour k);
      for l=0 to 3 do
       Array.set arraycolours 3 (inttocolour l);
       for m=0 to 3 do
        Array.set arraycolours 4 (inttocolour m);
        if test arraycolours = t then raise Exit
       done
      done
     done
    done
   done
  with Exit -> arraycolours;;

But there says: Error: This expression has type colour array but an expression was expected of type unit

How can I return the array that meets condition?

like image 894
gmv92 Avatar asked Oct 20 '25 17:10

gmv92


2 Answers

Let's collapse your complex function definition by substituting your big for loop with the <big-for-loop> term.

let myfunction t =
 let arraycolours = Array.make 5 W in
  try
    <big-for-loop>
  with Exit -> arraycolours

The <big-for-loop> is actualy an expression, whose value () has type unit. The try/with expression, has the following syntax:

  try e1 with exn -> e2

Both e1 and e2 must return values of the same type. In you case the <big-for-loop> expression returns a value of type unit and the expression under the with clause has type colour array. This basically means, that depending on whether you were able to find a combination or not, your function will have different types. But types in OCaml can't depend on the runtime values, so we have a type error.

There are different solutions, depending on what you trying to implement, for example, you can raise Not_found exception if a combination wasn't found, e.g.,

let myfunction t =
 let arraycolours = Array.make 5 W in
  try
    <big-for-loop>;
    raise Not_found
  with Exit -> arraycolours

Alternatively, you can wrap the result into option type, and return Some array if the combination is found, and None otherwise:

let myfunction t =
 let arraycolours = Array.make 5 W in
  try
    <big-for-loop>;
    None
  with Exit -> Some arraycolours

I, personally, would prefer the latter solution.

like image 143
ivg Avatar answered Oct 22 '25 07:10

ivg


You should define a new exception type :

exception ExitArray of <type of arraycolor> (* may be "int array" in your case *) 

Then, when you want to exit from your loops : you raise an exception raise ExitArray arraycolors , at the end you catch the exception and collect the result:

  with Exit a -> a;;
like image 33
Pierre G. Avatar answered Oct 22 '25 07:10

Pierre G.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!