Неиспользуемая лексическая переменная - PullRequest
2 голосов
/ 29 марта 2019

только начал изучать шепот. Я понятия не имею, почему я получаю эти ошибки или даже что они значат. Я просто пытаюсь закодировать приближение числа Пи, используя ряд Грегори-Лейбница, вот код.

(defun gl (n)
           (defparameter x 0)                        ;init variable to hold our runnning sum
           (loop for y from 0 to n                   ;number of iterations, starting from 0 to desired n
              (if (= y 0)                                      ;if n is 0 then we just want 4
                 (defparameter w 4))
              (if (> y 0)                                      ;else, 4*(-1^y)/((2 * y)+1)
                 (defparameter w (* 4 (/ (exp -1 y) (+ (* 2 y) 1)))))
              (+ x w))                                         ;add to our running sum
           (write x))                                        ;once loop is over, print x.

Я попытался использовать setq, defvar, let и т. Д. Вместо defparameter, но я все еще получаю «Необъявленную свободную переменную X».

Я также получаю ошибку «Неиспользуемая лексическая переменная N», хотя я использую ее для своего цикла, что также странно.

Как я могу это исправить и почему это происходит? Спасибо!

1 Ответ

5 голосов
/ 29 марта 2019

Вот код после того, как 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)))))))
...