尝试用 SML 编写函数

Trying to write a function in SML

我正在尝试用 sml 编写一个函数,它将列表作为第一个参数,将数字作为第二个参数。结果应该是:greaterT [3,5,2,4,7]3; val it = [5,4,7] : int 列表

这是我目前的工作,但还没有完成。

fun greaterT ([],k) = []
|   greaterT (a::x,k)
if a <= k
then x = [] 
else greaterT(x,k);

你遇到了问题,因为 if 表达式的 then 分支试图做一些没有意义的事情:

x = []

虽然您可以使用 refs 实现可变性,但您不能将值重新分配给标准 ML 中已绑定的标识符,但在这种情况下不需要它们。

在您的情况下,所需函数在概念上所做的是查看列表的第一个元素,通过将其与 k 进行比较来决定是否将其保留在最终结果中,然后递归列表的其余部分:

fun greaterT ([], k) = []
  | greaterT (a :: rest, k) =
      if a <= k then
        a :: greaterT (rest, k)
      else
        greaterT (rest, k)

不过,以上不是一个好的解决方案,因为第一个递归调用不在尾部位置,所以编译器无法优化生成的代码(原因我不会在这里讨论;那里有很多 questions about tail-call optimizations on Whosebug).

因此,更好的版本会使用一个额外的参数,在该参数中它会累积满足 <= 谓词的元素。

fun greaterTailRec ([], k, result) = List.rev result
  | greaterTailRec (a :: rest, k) =
      if a <= k then
        greaterTailRec (rest, k, result)
      else
        greaterTailRec (rest, k, a :: result)

fun greaterT (list, k) = greaterTailRec (list, k, [])

我们可以更进一步,通过替换细节来概括 greaterTailRec,在这种特殊情况下是比较调用 <=,以更一般地调用接受元素的函数作为参数的列表和 returns a bool。因此,我们最终会得到一个通常有用的函数,称为 filter:

fun filter predicate list =
  let
    fun recur ([], result) = List.rev result
      | recur (a :: rest, result) =
          if predicate a then
            recur (rest, a :: result)
          else
            recur (rest, result)
  in
    recur (list, [])
  end

fun greaterT (list, k) =
  filter (fn a => a >= k) list

中的filter helper function is already defined on the List structure,所以你的初始函数可以更简洁的表示为:

fun greaterT (list, k) =
  List.filter (fn a => a >= k) list