1

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

如果给定的阈值是负数,您应该打印消息“错误:负阈值”并返回一个空列表。为此,定义一个名为 ThresholdOutOfRange 的异常,如果阈值为负数,则提高它,并处理异常以实现正确的行为。

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

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

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

4

2 回答 2

4

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

exp_1 handle pat => exp_2

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

(exp_1; ... ; exp_n) 

它本身就是一个表达式。这在下面展示

- (print "foo\n"; print "bar\n"; 42);
foo
bar
val it = 42 : int

从这里我们可以看到,序列的最终结果是exp_n评估结果。

由于序列经常用在 let 表达式中,因此可以写成以下(没有前面提到的括号)

let dec in exp_1 ; ... ; exp_n end

奖金信息

序列实际上是一系列案例的派生形式(句法糖)。以下

(expr_1 ; ... ; exp_n ; exp)

相当于

case expr_1 of _ => 
  case ... =>
    case exp_n of _ => exp
于 2013-04-08T22:43:17.233 回答
1
  • 首先,声明一个异常

    exception OutOfRangeException;
    
  • 定义将引发异常的函数:

    fun someFunc x =
      if x < 0 then 
        raise OutOfRangeException
      else [1,2,3,4] (*return some list*)
    
  • 最后,通过打印消息并返回空列表来处理异常的函数:

fun someFunc_test x=    
  (someFunc x) handle OutOfRangeException => (print "exception"; [])
于 2013-04-08T22:48:05.750 回答