尝试用 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 = []
虽然您可以使用 ref
s 实现可变性,但您不能将值重新分配给标准 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
我正在尝试用 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 = []
虽然您可以使用 ref
s 实现可变性,但您不能将值重新分配给标准 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