No terminating condition on the loop. To fix your code:
let rec somme1 x =
if x <= 0
then 0
else if ((x mod 3) = 0) or ((x mod 5) = 0)
then x + (somme1 (x-1))
else somme1 (x-1);;
somme1 1000;;
To improve your code, you'd make your function tail-recursive.
let rec somme2 x accum =
if x <= 0
then accum
else if ((x mod 3) = 0) or ((x mod 5) = 0)
then somme2 (x-1) (accum+x)
else somme2 (x-1) accum
somme2 1000 0;;
The difference between the two versions is that, in the tail-recursive case, the results of the recursive call are precisely the same as the result of the function, so no intermediate state needs to be stored to finish the calculation after the recursive function is called. When you call somme1 1000;;
then, because (1000 mod 5 == 0) or (1000 mod 3 == 0)
evaluates true
, you get the recursive call 1000 + (somme1 999)
, which, to complete, requires the recursive call 999 + (somme1 998)
. The compiler has to keep the numbers 1000
and 999
around on the stack until somme1
finishes executing, which it doesn't (no terminating condition), so your stack fills up trying to store 1000 + (999 + (996 + (995 + ...
.
This will be equivalent to ((((0 + 1000) + 999) + 996) + 995) + ...
, but in this case there are no intermediate values needed to work on the result of the recursive calls (that is, the return value of the recursive call is the same as the return value of the function itself), so no additional stack space is necessary. The second version works this way. If it had the same bug as the first, it would not have run out of stack, but would have just continued executing indefinitely. This is considered an improvement. :-)