Это поведение намекает на отсутствующую оптимизацию хвостового вызова, так что ваша рекурсия разрушает стек. Возможная причина в том, что вы объявили оптимизацию отладки.
Кстати, вам не нужно делать явный вызов return-from
. Поскольку sum
является самооценочным символом, вы можете изменить эту строку
(return-from count-reduced-fractions sum)
до
sum
edit: Объяснение предлагаемого изменения: «sum» возвращает свое собственное значение, которое становится возвращаемым значением оператора «if», который (так как это последний оператор в defun) становится возвращаемым значением функции.
edit: Объяснение объявленной оптимизации: Вы можете добавить следующее к своему верхнему уровню:
(declaim (optimize (speed 3)
(debug 0)))
или используйте то же самое, но с declare
вместо declaim
в качестве первого оператора в вашей функции. Вы также можете попробовать (пробел 3) и (безопасность 0), если это не сработает.
Оптимизация вызова Tail означает, что вызов функции, возвращаемое значение которой напрямую возвращается, преобразуется в замену кадра в стеке (вместо суммирования), эффективно «выравнивая» рекурсивный вызов функции в цикле и устраняя рекурсивную функцию. звонки. Это делает отладку немного сложнее, потому что нет вызовов функций там, где вы ожидаете их, соответственно. вы не знаете, как «глубоко» в рекурсии происходит ошибка (как если бы вы написали цикл для начала). Ваша среда может сделать некоторые декларации по умолчанию, которые необходимо переопределить, чтобы включить TCO.
edit: Просто вернемся к этому вопросу, что такое g
? Я думаю, что вы действительно хотите
(let ((g (gcd n d)))
;; ...
)