Неиспользуемая лексическая переменная

#lisp #common-lisp

#lisp #common-lisp

Вопрос:

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

 (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. Не используйте defparameter внутри defun . Вам следует проверить Hyperspec или какую-нибудь вводную книгу (рекомендации см. в разделе info), чтобы найти идиоматический способ определения локальных переменных с помощью let или внутри loop .

Ответ №1:

Вот код после того, как 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 and w и использовал SUM предложение цикла.

 (defun gl (n)
  (loop
     for y from 0 to n
     sum (if (zerop y)
             4
             (* 4 (/ (expt -1 y)
                     (1  (* 2 y)))))))
  

Комментарии:

1. Вау! Я понятия не имел, что делаю так много вещей неправильно, лол. Думаю, я привык владеть Python и c вручную. Спасибо за помощь!

2. @Matt это в основном зависит от того, насколько вы знакомы с ним, вы, вероятно, легко освоитесь с CL, который в некоторых отношениях проще, чем C и Python (например, меньше угловых случаев).

3. Вы говорите, что Python держит руку на пульсе? Мы можем скомпилировать def foo(x): ... return y в Python 3 без предупреждения, которое x не используется, или предупреждения, которое y не определено. Появляется .pyc файл, определяющий нерабочую скомпилированную функцию.