我正在尝试用递归学习F#和数组。我已经解决了使用递归来汇总数组的问题我现在正试图做同样的事情,除了这次匹配模式,但我无法让它工作帮助。
let myArray = Array.create 5 0
myArray.[0] <- 0
myArray.[1] <- 1
myArray.[2] <- 2
myArray.[3] <- 3
myArray.[4] <- 4
let rec sum (arr : int array) counter =
if counter = 0 then 0
else arr.[counter] + sum arr (counter - 1)
////////////////////////////////////////////////
// Can't get this to work.
let rec sum1 (arr : int array) counter =
match arr with
| [||] -> printfn "0"
| arr -> arr.[counter] + sum arr (counter - 1)
答案 0 :(得分:4)
您的实现存在的问题是,您希望不可变的arr
以某种方式从调用变为sum1
。它没有改变,所以你的实现是什么,但是当System.IndexOutOfRangeException
变为负数时,空数组会抛出counter
!
继续坚持使用索引进行操纵:
let rec sum1 (arr : int array) counter =
match counter with
| 0 -> 0
| _ -> arr.[counter - 1] + sum1 arr (counter - 1)
sum1 myarray (myarray.Length)
按预期返回10
。
此实施方式与sum
if-then-else
的第一个let myarray = Array.init 100000 id
不完美。要理解为什么只是尝试使用System.Stackoverflow
之类的东西运行它 - 它可能会抛出sum
异常。异常原因 - 它不是tail-recursive。
使其尾递归并不困难 - 只需添加一个累加器let rec sum1TR sum counter (arr: int[]) =
match counter with
| 0 -> sum
| _ -> sum1TR (sum + arr.[counter - 1]) (counter - 1) arr
即可完全解除后续调用的堆栈:
sum1TR 0 1000000 (Array.init 1000000 id)
现在summator
即使对于一百万个项目也是如此。
最后,由于你想获得数组元素的总和,有意义的是只向单个参数公开单个参数 - 数组本身,在外部函数中移动递归let sum (as: int[]) =
let rec summator s l =
match l with
| 0 -> s
| _ -> summator (s + as.[l - 1]) (l - 1)
summator 0 as.Length
:
{{1}}