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
所以我有这个代码:
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