我什至不知道从哪里开始指出您的代码存在的问题。您似乎误解了函数式编程的基础知识。
- 首先,您不应该使用引用(除非您知道自己在做什么,否则它可能仍然是错误的),您应该使用递归。
- 您还没有声明您的函数采用相同数量的参数。在第一个子句中,您使用 2 个 curried 参数定义了它,在其余子句中您只有一个参数,在代码的倒数第二行中,您使用一对作为参数调用函数。
- 您的第一个函数子句没有正文。
"<"
不是 sml 中的严格小于运算符。正如你在那里写的,它是一个字符串。
修复您的原始代码将导致类似这样的结果。请注意,第一个元素总是放回列表中,这样我们就知道要比较什么。
fun findlarger [] = 0
| findlarger [x] = 0
| findlarger (x::y::xs) =
if y > x*2 then
1 + findlarger(x :: xs)
else
findlarger(x :: xs)
但是,您也可以使用内部辅助函数完成 x*2 的计算,这样就不会每次都计算
fun findlarger [] = 0
| findlarger (x::xs) =
let
val xx = 2*x
fun f [] = 0
| f (y::ys) =
(if y > xx then 1 else 0) + f ys
in
f xs
end
如果使用另一个答案中建议的高阶函数,那么您应该避免遍历列表两次(首先过滤掉元素,然后计算剩余的元素)。您应该只浏览一次列表,并计算与给定谓词匹配的元素。
要完成此功能,您可以使用其中一种折叠功能。在大多数情况下,使用 foldl 是有意义的,因为它将以尾递归的方式从左到右遍历列表。
fun p (x, y) = if y > 2*x then 1 else 0
fun f [] = 0
| f (x::xs) = foldl (fn (a,b) => b + p(x, a)) 0 xs