gpt4 book ai didi

sml - 如何从另一个函数捕获 SML 中的异常?

转载 作者:行者123 更新时间:2023-12-05 09:18:19 26 4
gpt4 key购买 nike

我相信我对在 SML 中捕获异常有一些基本的误解。

我写了下面的代码:

    fun my_g acc p =
let
val r = my_g acc
in
case p of
Wildcard => acc
| Variable x => if List.exists (fn y => y = x) acc then raise NoAnswer else x::acc
| TupleP ps => List.foldl (fn (p,i) => (my_g i p)) acc ps
| ConstructorP(_,p) => r p
| _ => acc
end

(* val check_pat = fn : pattern -> bool *)
fun check_pat p =
if my_g [] p <> [] then
true
else
true
handle NoAnswer => false

我很乐意详细解释代码,但基本上我是想看看字符串是否在列表中重复。如果我发现重复的字符串,我会引发异常。请注意,我正在处理调用函数 my_g 的函数 check_pat 中的异常。但是,当我使用一些测试方法运行代码时,出现未捕获的异常 NoAnswer

我能否在另一个(调用)函数中捕获一个函数中抛出的异常?我做错了什么?

谢谢,戴夫

安德烈亚斯和 future 观众的更多细节。最初的提示是首先展开结构并获得字符串列表,然后才遍历并查找重复项。我觉得这样效率低下,最好在展开时查找重复项。不幸的是,我的 SML 知识还不足以提出一个 super 干净的解决方案。真的,我不关心 my_g 的返回值。如果它没有抛出异常,则没有重复项。就如此容易。但似乎语法规则迫使我检查返回值。既然你已经为我解决了“句柄”问题,我可能会重新审视这个问题。我希望只写:

(my_g [] p
true)
handle NoAnswer => false

但这似乎没有用。更广泛地说,虽然我认为我的解决方案比首先展开整个列表然后查找重复项更有效,但我怀疑像我一样使用异常的想法不是好的风格。在我熟悉的语言(C++、C#)中,异常意味着发生了一些异常或意外情况。查找重复字符串当然不是异常(exception)。同样,我确信还有另一种方法可以在不使用异常的情况下停止在第一个重复项上。我只是不够精通 SML 以了解它。谢谢!

最佳答案

这只是括号的问题:handleif 绑定(bind)得更紧密,所以你已经有效地编写了

if ... then ... else (... handle ...)

相反,你想要

(if ... then ... else ...) handle ...

所以你需要放在括号里。

顺便说一句,我无法理解您对 if 的使用——当两个分支产生相同结果时为什么要有条件?此外,if A then true else BA orelse B 的冗长表达方式。

编辑 回复问题中的编辑:如果您想忽略表达式的结果并返回其他内容,那么您可以使用分号运算符:

(my_g [] p; true)

但是,一般来说,不推荐对非异常控制流使用异常。有一种更简洁的方法来编写此函数:

fun ids (Variable x)       = [x]
| ids (Tuple ps) = List.concat (List.map ids ps)
| ids (Constructor(_,p)) = ids p
| ids _ = []

fun hasDups [] = false
| hasDups (x::xs) = List.exists (fn y => y = x) xs orelse hasDups xs

fun checkPat p = not (hasDups (ids p))

编辑 2:在正常情况下(没有重复项),此解决方案并不比其他解决方案慢。所以不一定值得走捷径。但是,如果您坚持,有多种选项不需要异常(exception)。例如:

fun checkPat'(_, NONE)               = NONE
| checkPat'(Variable x, SOME xs) = if List.exists (fn y => y = x) xs then NONE else SOME (x::xs)
| checkPat'(Tuple ps, xso) = List.foldl checkPat' xso ps
| checkPat'(Constructor(_,p), xso) = checkPat'(p, xso)
| checkPat'(_, xso) = xso

fun checkPat p = isSome (checkPat'(p, SOME []))

或者,如果您愿意使用一些可变状态:

fun checkPat' xs (Variable x)       = List.exists (fn y => y = x) (!xs) before (xs := x :: !xs)
| checkPat' xs (Tuple ps) = List.all (checkPat' xs) ps
| checkPat' xs (Constructor(_,p)) = checkPat' xs p
| checkPat' xs _ = true

fun checkPat p = checkPat' (ref []) p

关于sml - 如何从另一个函数捕获 SML 中的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44980932/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com