与任何递归问题一样,您的基本情况是什么?我想说在这种情况下,两个列表都是空的,它给你一个空列表。
fun repeat([], []) = []
如果一个是空的而另一个不是呢?那是失败的。让我们定义一个在发生这种情况时可以抛出的异常。
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
现在真正的问题是我们在剩下的时间里做什么。幸运的是,SML 可以轻松地对两个列表进行模式匹配并提取它们的第一个元素。
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) = ...
此时,我们需要一个递归函数来重复列表中的一个元素一定次数。与整体功能一样,这里我们看到递归的两个标志:至少一个基本“退出”条件,以及通过将n 更新为@987654325 向基本条件收敛的更新步骤@。
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) =
let
fun repeat'(_, 0) = []
| repeat'(x, n) = x :: repeat'(x, n - 1)
in
...
end
现在,我们只需要将它们放在一起,将x 和y 输入到repeat',然后将其与再次调用repeat 的结果与xs 和ys 连接起来。通过这样做,我们会收敛到repeat([], []) 的基本情况或,我们可能会收敛到引发MismatchedArguments 异常的不匹配场景。
exception MismatchedArguments;
fun repeat([], []) = []
| repeat([], _) = raise MismatchedArguments
| repeat(_, []) = raise MismatchedArguments
| repeat(x::xs, y::ys) =
let
fun repeat'(_, 0) = []
| repeat'(x, n) = x :: repeat'(x, n - 1)
in
repeat'(x, y) @ repeat(xs, ys)
end
现在repeat([1, 2, 3], [4, 0, 3]) 将产生[1, 1, 1, 1, 3, 3, 3]。