Нет завершающего условие цикла. Чтобы исправить ваш код:
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;;
Чтобы улучшить код, вы должны сделать свою функцию хвостовой рекурсивной.
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;;
Различие между двумя версиями является то, что, в хвостовой рекурсии случае, результаты рекурсивного вызова в точности такой же, как результат функции, поэтому никакого промежуточного состояние не должно быть сохранено, чтобы закончить вычисляется после рекурсивной функции. Когда вы вызываете somme1 1000;;
, то, поскольку (1000 mod 5 == 0) or (1000 mod 3 == 0)
оценивает true
, вы получаете рекурсивный вызов 1000 + (somme1 999)
, который, для завершения, требует рекурсивного вызова 999 + (somme1 998)
. Компилятор должен хранить номера 1000
и 999
в стеке до тех пор, пока somme1
не завершит выполнение, что не будет (условие завершения), поэтому ваш стек заполняется, пытаясь сохранить 1000 + (999 + (996 + (995 + ...
.
Это будет эквивалентно ((((0 + 1000) + 999) + 996) + 995) + ...
, но в этом случае нет промежуточных значений, необходимых для работы с результатом рекурсивных вызовов (то есть возвращаемое значение рекурсивного вызова совпадает с возвращаемым значением сама функция), поэтому дополнительное пространство стека не требуется.Вторая версия работает именно так. Если бы у него была такая же ошибка, как у первой, у нее не было бы стека, но она бы продолжала работать бесконечно. Это считается улучшением. :-)
Главное, что я вам месте» вы сделали неправильно, пытается решить эту проблему, используя рекурсивную функцию ... – danii
Вы должны перезапустить интерпретатор caml: он использует старое определение somme в somme2, поэтому вам не нужно использовать ключевое слово rec во втором определении. Использовать let rec ... = ... и ... = ... ;; Это должно работать, за исключением того, что вы должны написать, если x = 0, тогда 0 else somme2 x, потому что «return x» вводит в заблуждение. – gnomnain