Вот код после того, как Emacs автоматически его отступил:
(defun gl (n)
(defparameter x 0)
(loop for y from 0 to n
(if (= y 0)
(defparameter w 4))
(if (> y 0)
(defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
(+ x w))
(write x))
Компиляция следующего кода с SBCL дает одну ошибку и два предупреждения.
В одном предупреждении говорится, что x
не определено.
Вы не должны вызывать defparameter
изнутри вашей функции, поскольку defvar
и defparameter
используются для объявления динамических переменных и установки их значения в глобальной области видимости. Предпочитайте привязки let или, поскольку вы уже используете цикл, предложение with
. Если вы хотите изменить привязку, используйте setf
.
Ошибка возникает из-за макроразложения LOOP
, которое искажено. Для SBCL это означает, что код обрабатывается как мертвый код для остальной части компиляции функции; это объясняет, почему n
кажется неиспользуемым, о чем и говорится во втором предупреждении.
Осталось сделать еще несколько исправлений:
- Используйте функцию
EXPT
, а не EXP
.
- Вызов
(+ x w)
только вычисляет значение, но не изменяет x
, результат бесполезен.
- Предпочитайте использовать
if
в качестве выражения, как троичный оператор в других языках, в вашем случае код может быть упрощен
- Добавление одного можно сделать с помощью функции
1+
(это имя функции, а не специальный синтаксис для добавления констант)
- Операция
write
требуется редко, особенно если вы вычисляете математическую формулу; просто верните значение, и REPL распечатает его автоматически.
Небольшие исправления, которые делают ваш код работоспособным:
(defun gl (n)
(let ((x 0))
(loop
for y from 0 to n
for w = (if (= y 0)
4
(* 4 (/ (expt -1 y) (+ (* 2 y) 1))))
do (setf x (+ x w)))
(write x)))
Я бы лично избавился от x
и w
и использовал бы предложение SUM
loop.
(defun gl (n)
(loop
for y from 0 to n
sum (if (zerop y)
4
(* 4 (/ (expt -1 y)
(1+ (* 2 y)))))))