OCaml:遇到异常时,for循环应该忽略它并继续,而不会把我扔出去

OCaml: Upon encountering an exception, the for cycle should just ignore it and continue without tossing me out

所以我有这个代码:

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;

我希望异常处理程序在不打印作品的情况下继续循环,而不是它把我扔出去,但仍然给我一个异常。我在这里做错了什么?

当我编译这个时,我得到:

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)

好吧,你忽略了这个,所以当我 运行 它时,我得到:

worksworksworksException: Invalid_argument "index out of bounds".

"Index out of bounds""index out of bounds" 不同。您捕获了错误的异常。

Goswin 关于匹配异常时大小写不匹配的说法是正确的。您的代码中也有不必要的分号,因为您没有将多个表达式链接在一起。

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

另请注意,在OCaml 4.02及以后的版本中,我们可以直接在match中处理异常,所以这段代码可以表示为:

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

如果您希望完全避免异常处理,您可以非常简单地进行边界检查。

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

一般情况下,Invalid_argument _ 异常不应被捕获或匹配。 这些异常是指应在发生之前避免的编程错误。在这种特定情况下,这意味着在使用索引之前检查索引是否在矩阵的范围内。

例如:

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

也可以定义一个矩阵访问运算符 returns 一个选项类型,以便分解循环外的边界检查:

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