Reputation: 1
So i have this code:
let matrix = [|
[| true; true; true |];
[| false; false; false |];
[| false; true; true |];
[| true; false; false |]
|];;
for i = 0 to 10 do
for j = 0 to 10 do
try
if matrix.(i).(j) = true then
print_string "works"
with
| Invalid_argument "Index out of bounds" -> ();
done;
done;
I want the exception handler to just continue the loop without printing works, instead it tosses me out and still gives me an exception. What am i doing wrong here?
Upvotes: 0
Views: 133
Reputation: 18902
In general, Invalid_argument _
exceptions should not be catch nor matched.
Those exceptions are meant as programming errors that should be avoided before they happen. In this specific case, this means checking that the indices are within the bound of the matrix before using them.
For instance:
for i = 0 to 10 do
for j = 0 to 10 do
if i < Array.length matrix && i >= 0
&& j < Array.length matrix.(i) && j >= 0
&& a.(i).(j)
then print_string "works"
done
done
It is also possible to define a matrix access operator that returns an option type in order to factorize the bound checking outside of the loop:
let (.?()) a (i,j) =
if i < Array.length a && i >= 0
&& j < Array.length a.(i) && j >=0
then
Some (Array.unsafe_get (Array.unsafe_get a i) j)
else None
for i = 0 to 10 do
for j = 0 to 10 do
match matrix.?(i,j) with
| None | Some false -> ()
| Some true -> print_string "work"
done
done
Upvotes: 1
Reputation: 36611
Goswin is correct about the case mismatch in matching the exception. You also have unnecessary semicolons in your code as you are not chaining multiple expressions together.
for i = 0 to 10 do
for j = 0 to 10 do
try
if matrix.(i).(j) = true then
print_string "works"
with
| Invalid_argument _ -> ()
done
done
Also note that in OCaml 4.02 and later, we can handle exceptions directly in a match
, so this code could be expressed as:
for i = 0 to 10 do
for j = 0 to 10 do
match matrix.(i).(j) with
| true -> print_string "works"
| false | exception Invalid_argument _ -> ()
done
done
If you wish to avoid the exception handling altogether, you could quite simply bounds check.
let height = Array.length matrix in
for i = 0 to (min 10 (height - 1)) do
let width = Array.length matrix.(i) in
for j = 0 to (min 10 (width - 1)) do
if matrix.(i).(j) then
print_string "works"
done
done
Upvotes: 1
Reputation: 12342
When I compile this I get:
Warning 52: Code should not depend on the actual values of
this constructor's arguments. They are only for information
and may change in future versions. (See manual section 9.5)
Well, you ignored this, so when I run it I get:
worksworksworksException: Invalid_argument "index out of bounds".
"Index out of bounds"
is not the same as "index out of bounds"
. You are catching the wrong exceptions.
Upvotes: 2