OCAML:遇到例外后,for循环应该忽略它并继续而不会抛弃我

发布于 2025-01-27 15:21:16 字数 427 浏览 0 评论 0原文

因此,我有此代码:

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;

我希望例外处理程序只能在没有打印作品的情况下继续循环,而是将我扔掉,但仍然给我一个例外。我在这里做错了什么?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

披肩女神 2025-02-03 15:21:16

当我对此进行编译时,我会得到:

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 of Bounds”“ index of Bounds” 。您遇到了错误的例外。

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.

爱你不解释 2025-02-03 15:21:16

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

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
穿越时光隧道 2025-02-03 15:21:16

通常,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

也可以定义一个矩阵访问操作员,该矩阵访问操作员返回选项类型,以便对循环外的界限进行分配:

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文