For summing the first three elements of a list, your approach seems quite reasonable. Now imagine you're asked to sum the first five. What about the first twenty?
Yes, you do cover all of the cases, but it's possible to think of this in terms of just two cases using recursion.
We know that if we want to sum the first zero elements of any list, we'll get 0
. Likewise, if we want to sum the first n
numbers in an empty list, we'll get 0
. So the only time that doesn't yield 0
is a non-empty list when n
is greater than zero.
In that case we add the first element to summing n - 1
elements of the tail of the list. Applying the function recursively to the tail and decrementing n
will converge our function on the base case which returns 0
.
# let rec sum_first_n n lst =
match lst with
| x::xs when n > 0 -> x + sum_first_n (n - 1) xs
| _ -> 0;;
val sum_first_n : int -> int list -> int = <fun>
# sum_first_n 3 [7; 8; 9; 10];;
- : int = 24
sum_first_n 3 [7; 8; 9; 10]
7 + sum_first_n 2 [8; 9; 10]
7 + 8 + sum_first_n 1 [9; 10]
7 + 8 + 9 + sum_first_n 0 [10]
7 + 8 + 9 + 0
24
We could also use sequences (since OCaml 4.07) to take the first n
elements and then fold +
over them.
# let sum_first_n n lst =
lst
|> List.to_seq
|> Seq.take n
|> Seq.fold_left (+) 0;;
val sum_first_n : int -> int list -> int = <fun>
# sum_first_n 3 [7;8;9;10];;
- : int = 24