第一件事:
-
index 应该有两个参数;要查找的元素和要在其中查找的列表。
累加参数属于辅助函数。
- 总是产生
SOME的东西而不是NONE是没有意义的。
让我们先解决这些问题。
fun index (item, xs) =
let
fun index'(m, nil , ys) = ys
| index'(m, x::xr, ys) = if x = item then(
(ys @ [m]);
index'(m + 1, xr , ys)
)
else index'(m + 1, xr,ys)
in
index'(0, xs, [])
end;
现在您在使用index 时不需要传递额外的累加器参数。
也不能从[]以外的东西开始。
你的下一个主要问题是
(ys @ [m]);
index'(m + 1, xr , ys)
它首先创建列表ys @ [m],立即将其丢弃,然后生成index'(m + 1, xr , ys),这正是else 分支所做的。
即条件等价于
if x = item
then index'(m + 1, xr, ys)
else index'(m + 1, xr, ys)
因此,index' 等价于
fun index'(m, nil, ys) = ys
| index'(m, x::xr, ys) = index'(m + 1, xr, ys)
由于您始终传递原始的ys,并且以[]开头,因此结果始终为[]。
你需要做的就是将扩展列表传递给递归,这样它就可以成为递归终止时的结果。
重命名累加器ys 使其用途更清晰:
fun index (item, xs) =
let
fun index'(i, nil, accumulator) = accumulator
| index'(i, x::xr, accumulator) = if x = item
then index' (i + 1, xr, accumulator @ [i])
else index' (i + 1, xr, accumulator)
in
index'(0, xs, [])
end;
这是低效的,因为重复将一个元素附加到列表的后面。
逆向累积是很常见的,完成后更正它。
(这“感觉”效率低下,但事实并非如此。)
fun index (item, xs) =
let
fun index'(i, nil, accumulator) = List.reverse accumulator
| index'(i, x::xr, accumulator) = if x = item
then index' (i + 1, xr, i::accumulator)
else index' (i + 1, xr, accumulator)
in
index'(0, xs, [])
end;