如何引发打印消息并返回值的异常?

mur*_*rby 2 exception sml

我们的教授要求我们在作业中这样做:

\n\n
\n

如果给定的阈值为负,则应打印消息 \xe2\x80\x9cError: Negative Threshold\xe2\x80\x9d 并返回空列表。为此,需要 de\xef\xac\x81ne 一个名为 ThresholdOutOfRange 的异常,如果阈值为负则引发该异常,并处理该异常以实现正确的行为。

\n
\n\n

我不明白如何引发异常、返回值和打印错误消息。现在我引发异常的代码是(只是有异常的重要部分):

\n\n
fun getnearbylist(center, threshold, ziplist) =\n    let\n      exception ThresholdOutOfRange;\n      fun test_threshold(threshold, zip, nil) =nil\n      |   test_threshold(threshold, zip, ziplist as x::xs) =\n          if (threshold <0.0) then raise ThresholdOutOfRange\n(*        [...skipped a long unrelated middle bit. most important is just knowing\n              this function returns a string list...] *)\n          else x::test_threshold(threshold, zip, xs)\n    in\n      test_threshold(threshold, center, ziplist)\n      handle\n      ThresholdOutOfRange => []\n    end\n
Run Code Online (Sandbox Code Playgroud)\n\n

因此,当引发异常时,我的代码将仅返回一个空列表。鉴于据我所知,异常必须具有与它们引发的函数相同的返回类型,我该怎么做才能返回空列表并打印错误消息?

\n

Jes*_*erg 5

异常处理的结果类型必须与处理异常的表达式相同是正确的。换句话说,exp_1并且exp_2在下面的代码中必须具有相同的类型,就像“then”和“else”一样if 表达式的一部分。

exp_1 handle pat => exp_2
Run Code Online (Sandbox Code Playgroud)

因此,您正在寻找一种在该exp_2部件中执行多种操作的方法,特别是具有打印消息副作用的操作。对于这样的事情,你可以使用序列。序列具有以下形式(注意括号)

(exp_1; ... ; exp_n) 
Run Code Online (Sandbox Code Playgroud)

这本身就是一种表达。这在下面得到了证明

- (print "foo\n"; print "bar\n"; 42);
foo
bar
val it = 42 : int
Run Code Online (Sandbox Code Playgroud)

由此我们可以看出,序列的最终结果就是计算结果exp_n

由于let表达式中经常使用序列,因此允许编写以下内容(没有前面提到的括号)

let dec in exp_1 ; ... ; exp_n end
Run Code Online (Sandbox Code Playgroud)

奖金信息

序列实际上是一系列情况的派生形式(语法糖)。下列

(expr_1 ; ... ; exp_n ; exp)
Run Code Online (Sandbox Code Playgroud)

相当于

case expr_1 of _ => 
  case ... =>
    case exp_n of _ => exp
Run Code Online (Sandbox Code Playgroud)