将数字相加并除以长度。简单的递归
sum
通常是任何SML教程中您会看到的第一个示例。您需要将
sum
的空列表基础情况评估为
0.0
而不是
0
,以确保返回类型为
real
。一旦定义了
sum
函数,就可以使用
sum
和内置的
length
函数在1行中定义
average
。一个微妙之处是SML不允许将实数除以整数。在将总和除以长度之前,您可以在长度上使用转换函数
Real.fromInt
。在传递相同的列表两次(一次求和,一次计算长度)方面存在一些低效性,但是当您首次学习语言时,没有理由担心这些问题。
编辑:由于您已经找到了自然的解决方案并在评论中分享了它,这里是一个更习惯用法的版本,它在列表上进行了一次平均值计算:
fun average nums =
let
fun av (s,n,[]) = s/Real.fromInt(n)
| av (s,n,x::xs) = av (s+x,n+1,xs)
in
av (0.0, 0, nums)
end;
它的工作原理是定义一个助手函数来完成繁重的工作。这在函数式编程中被广泛使用。在没有可变状态的情况下,一种常见的技巧是将数量明确地作为参数传递,这些数量将在相应循环中被依次修改。这些参数通常称为累加器,因为它们通常累积增长的列表、运行总和、运行乘积等。这里的 s 和 n 是累加器,其中 s 是元素的和,n 是列表的长度。在基础情况下,即 (s,n,[]),没有更多的累积内容,因此返回最终答案。在非基础情况下,即 (s,n,x::xs),s 和 n 会被适当地修改,并与列表的尾部一起传递给助手函数。av 的定义是
tail-recursive,因此可以像循环一样快速运行而不会增加堆栈。整个 average 函数需要做的唯一事情就是使用适当的初始值调用助手函数。let ... helper def ... in ... helper called with start-up values ...end 是一种常见的习惯用法,用于防止程序的顶层被助手函数淹没。
fun sum(h::t)=h + sum(t) | sum(nil)=0.0;
长度函数:fun length(h::t) = 1.0 + length(t) | length(nil) = 0.0;
完整函数:fun average(l) = sum(l) / length(l);
- opheliaxo