2012-02-21 56 views
0

我的作业是实现一个程序,该程序采用函数和二叉树并从二叉树输出满足函数的整数列表(例如:如果数字是偶数,则函数返回true,因此程序的输出将是一个偶数列表)。SML中的值异常

我这里的代码:

datatype 'a tree = Empty | Node of ('a tree  * int * 'a tree) 

    fun collect (p, Empty) = [] 
    |collect (p, Node (L, x, R)) = 
    if (p x) then x :: (collect (p, L) @ collect (p, R)) 
    else 
    collect (p, L) @ collect (p, R); 

,工作正常,但分配要求我实现与例外此功能。我们应该利用价值的载体功能,但我的代码是行不通的:

fun collect (p, Empty) = [] 
     | collect (p, (Node(L, x, R))) = 
     if (p x) then (raise FoundSoFar [x]) 
     else 
      (collect (p, L))@(collect (p, R)) 
    handle FoundSoFar x => x @ (collect (p, L))@(collect (p, R)) 

其编译正确,但是当我尝试由老师给出的测试代码:

val L = Node (Node (Empty, 2, Empty), 5, Node (Empty, 6, Empty)); 
    val R = Node (Empty, 12, Empty); 
    val T = Node (Node (L, 7, Node (Empty, 8, Empty)), 11, R); 

    val r = collect ((fn x => (x mod 2) = 0) , T); 

我只是得到未捕获的异常错误...... 我需要帮助了解我的代码有什么问题,如何解决它,以及\或者如何在SML中正确实现带有值的异常,任何事情都会有所帮助,谢谢。

+0

有更高的优先级你得到了哪个例外?你的FoundSoFar不是一个有价值的例外吗? – 2012-02-21 07:47:43

+0

它编译,它不工作。它实际上说未被发现的异常。 – Arsarcanum 2012-02-21 07:53:03

+0

考虑一下你在做什么:你正在寻找一个在左右子树中满足“p”的元素。如果找到一个,就会抛出一个异常,然后再次执行相同的搜索。所以,自然你会得到同样的异常再次抛出。 – 2012-02-21 08:17:43

回答

1

你的这部分代码没有意义:

 (collect (p, L))@(collect (p, R)) 
handle FoundSoFar x => x @ (collect (p, L))@(collect (p, R)) 

如果handle部分运行,这意味着(collect (p, L))@(collect (p, R))抛出异常。但是,当你处理它时你做了什么?您再次评估完全相同的表达(作为句柄表达式右侧的一部分)。所以很自然,这种评价将失败,并再次抛出完全相同的异常,有点像这样:

(collect (p, L))@(collect (p, R)) handle FoundSoFar x => raise FoundSoFar x 

那么到底,这是因为如果你没有抓住摆在首位的例外:

(collect (p, L))@(collect (p, R)) 

您可能想要发现异常,然后对您捕获的值执行一些有用的操作,但而不是运行的引导异常的表达式完全相同。

P.S.您想要考虑的代码中另一个与您无关的问题是优先级。 handleif-then-else