计算阵列的长度而不会炸毁堆栈

时间:2016-07-07 14:44:21

标签: f#

如何在不炸毁堆叠的情况下计算阵列的长度?我的两次尝试对我来说都不好看

let rec slowComputeLength xs = match xs with
                               | x::xss -> 1 + slowComputeLength xss
                               | _ -> 0

let computeLength xs = List.fold (fun acc _ -> acc + 1) 0 xs

我可以考虑在模式匹配的第一个版本中传递累加器,但这会使API变得难看

let rec slowComputeLength xs acc = match xs with
                                   | x::xss -> slowComputeLength xss acc+1
                                   | _ -> 0

List.fold是正确的方式还是创建类似下面的东西,我相信它也会打到堆栈?

(1 + (1 + (1 + (...))))?

PS - 我这样做是为了练习,理想情况下我们应该使用Array.Length。

1 个答案:

答案 0 :(得分:5)

通常的技巧是定义一个嵌套的递归函数来保存累加器:

let computeLength xs = 
  let rec loop acc xs = 
    match xs with
    | _::xs -> loop (acc+1) xs
    | _ -> acc
  loop 0 xs

这里,loop函数有额外的累加器参数,但它不会使外部computeLength函数的API变得丑陋,因为loop函数是嵌套的,从不直接调用由用户。