1

我试图在之前在代码中抛出异常后添加捕获异常的机制,但我无法编译它:

这是没有异常处理的代码 - 它编译并且工作得很好:

fun calc(input : string ) : int = 


    let 
        val outStr = ref "someString"
        val outInt = ref 0

    in 
        (
            outStr := replaceRomanDec(input);       (* replace roman number with decimal *)
            outInt := calcMyRomanExpression(!outStr)    

        );

        (!outInt)

    end;

但是当我尝试把handleand放在exception 这里时:

fun calc(input : string ) : int = 

    exception CalculatorParser

    let 
        val outStr = ref "someString"
        val outInt = ref 0

    in 
        (
            outStr := replaceRomanDec(input);       (* replace roman number with decimal *)
            outInt := calcMyRomanExpression(!outStr);
            handle CalculatorParser =>  -1
        );

        (!outInt)



    end;

我得到:

stdIn:1761.2-1761.28 Error: syntax error: deleting  EXCEPTION ID
-               );
=
=               (!outInt)
=
=
=
=       end;
stdIn:1576.1-1757.2 Error: syntax error: deleting  RPAREN SEMICOLON

-

我尝试按照错误中的建议添加/删除分号,但没有任何效果。

知道有什么问题吗?

亲切的问候

4

1 回答 1

3

您似乎误解了表达式的序列 (expr_1; expr_2; ...; expr_n) 是如何工作的。

首先,没有必要先将 outStr 和 outInt 按自己的顺序“分组”,只是为了在另一个序列中使用它。

其次,我们不需要在in ... end局部声明(let)部分的序列周围加上括号,因为有一个派生形式(语法糖)来处理它。

此外,无需在“取消引用”周围添加括号。

所以一个简化的版本看起来像这样。

fun calc (input : string ) : int =
    let
      val outStr = ref "someString"
      val outInt = ref 0
    in
      outStr := replaceRomanDec input;       (* replace roman number with decimal *)
      outInt := calcMyRomanExpression (!outStr);
      !outInt
    end

句柄的语法是:

exp ::= ... | exp 句柄 匹配| ...

因此,句柄的左侧必须是一个表达式。您已将其作为序列的最后一部分 (exp_1 ; expr_2; expr_3):

expr_1   =>   outStr := replaceRomanDec(input);
expr_2   =>   outInt := calcMyRomanExpression(!outStr);
expr_3   =>   handle CalculatorParser => -1

从图中我们看到,句柄左侧没有提供表达式。因此,您会收到语法错误。

由于您的异常处理的结果是-1,我假设它是引发 CalculatorParser 异常的 calcMyRomanExpression。因此,一个解决方案可能是:

fun calc(input : string ) : int =
    let
      val outStr = ref "someString"
      val outInt = ref 0
    in
      outStr := replaceRomanDec(input);       (* replace roman number with decimal *)
      outInt := (calcMyRomanExpression(!outStr) handle CalculatorParser => ~1);
      !outInt
    end

还要记住,减一~1在 SML 中。


正如我在对您的问题的评论中指出的那样,您在进行函数式编程时确实应该停止使用引用。如果你需要使用它们,那么你几乎总是做错了。

如果您保持它的功能,那么代码可能很简单:

fun calc1 input = (calcMyRomanExpression o replaceRomanDec) input

甚至更简单

val calc2 = calcMyRomanExpression o replaceRomanDec
于 2013-01-03T22:56:21.850 回答