Ошибки
Оценка этой функции возвращает только название функции.
Я не могу повторить это, как вы тестировали свой код, в какой среде?
С SBCL вот что оценивает отпечатки формы defun
:
; in: DEFUN NSUM
; (N = 0)
;
; caught WARNING:
; undefined variable: =
Символ =
используется в позиции, где он оценивается как переменная.Если вы хотите вызвать функцию, связанную с =
, то есть (function =)
, что также может быть записано #'=
, тогда вам нужно написать (= ... ...)
.
; caught STYLE-WARNING:
; undefined function: N
Поскольку вы написали (N = 0)
, то есть с N
в качестве первого элемента формы при нормальных правилах оценки, код пытается вызвать функцию N
.В вашем случае вы не определили такую функцию.
; (COND ((MOD N 5) = 0) (NSUM (- N 1) (+ SUM N)) ((MOD N 3) = 0)
; (NSUM (- N 1) (+ SUM N)) (NSUM (- N 1) (+ SUM N)))
; --> IF
; ==>
; (IF NSUM
; (PROGN (- N 1) (+ SUM N))
; (IF (MOD N 3)
; (PROGN = 0)
; (IF NSUM
; (PROGN (- N 1) (+ SUM N))
; (IF NSUM
; (PROGN # #)
; NIL))))
;
; caught WARNING:
; undefined variable: NSUM
Вы пишете предложения cond, и в этом контексте каждое предложение должно быть списком, соответствующим (test . body)
, то есть выражением test
сопровождаемый корпусом (возможно, пустым).Вы писали:
(cond ( (mod n 5) = 0) ( nSum ( - n 1) (+ sum n)) ...)
В приведенном выше у вас есть два предложения, одно из которых (пытается) проверяет, делится ли N
на 5, а другое проверяет, является ли nSum
истинным.
; (SUM)
;
; caught STYLE-WARNING:
; undefined function: SUM
Вы добавили круглые скобки вокруг SUM
, что означает, что вы хотите вызвать функцию SUM
(в настоящее время не определено).Скобки имеют значение в Лиспе.
Исправление ошибок и форматирование
Вот ваш код после исправления предыдущих ошибок и форматирования его в соответствии с правилами стиля Lisp:
(defun nSum (n sum)
(if (= n 0)
sum
(cond
((= 0 (mod n 5)) (nSum (- n 1) (+ sum n)))
((= 0 (mod n 3)) (nSum (- n 1) (+ sum n)))
(t (nSum (- n 1) (+ sum n))))))
Ваш код не вычисляет желаемую функцию.Пожалуйста, прочитайте ответ Гванг-Джин Кима , чтобы узнать, как вычислить его хвост-рекурсивным способом, или ниже для основанного на цикле.
Некоторые дополнительные замечания относительно стиля:
Вы не должны использовать snakeCase в Лиспе, вместо этого используйте тире для разделения слов, смиренно известных как lisp-case (и, очевидно,также как kebab-case
).
Ваши if
и cond
могут быть объединены вместе.Кроме того, будьте осторожны с отрицательными значениями N
.
Вы можете сделать (or test1 test2)
, когда оба теста приводят к выполнению одного и того же кода.Это позволяет избежать дублирования кода.
Альтернативная реализация
Использование LOOP
:
(defun euler-1 (n)
(loop
for i below n
when (or (zerop (mod i 3))
(zerop (mod i 5)))
sum i))