Reputation: 1
I'm trying yo learn F# and arrays with recursion. I have solved summarizing an array with recursion now I'm trying to do the same thing except this time with match pattern but I can't get it to work help.
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)
Upvotes: 0
Views: 3606
Reputation: 10350
The problem with your implementation is that you expect immutable arr
somehow changing from call to call to sum1
. It does not change, so your implementation for anything, but empty array will be throwing System.IndexOutOfRangeException
when counter
gets negative!
Continue sticking to manipulation with the index:
let rec sum1 (arr : int array) counter =
match counter with
| 0 -> 0
| _ -> arr.[counter - 1] + sum1 arr (counter - 1)
And sum1 myarray (myarray.Length)
returns 10
as expected.
This implementation is not perfect as well as your first one sum
with if-then-else
. To understand why just try running it with something like let myarray = Array.init 100000 id
- it will likely throw System.Stackoverflow
exception. Cause of exception - it is not tail-recursive.
Making it tail-recursive is not difficult - just add an accumulator sum
that fully unties subsequent calls stack-wise:
let rec sum1TR sum counter (arr: int[]) =
match counter with
| 0 -> sum
| _ -> sum1TR (sum + arr.[counter - 1]) (counter - 1) arr
Now sum1TR 0 1000000 (Array.init 1000000 id)
works even for an array of a million items.
Finally, as you want to get a sum of array's elements it make sense to expose to end user only single parameter - the array per se, moving recursive summator
inside the external function:
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
Upvotes: 4