#common-lisp #sbcl
#common-lisp #sbcl
Вопрос:
При выполнении приведенного ниже кода в sbcl repl я получаю предупреждение «неопределенная переменная» для тестовых примеров переменных, n. Я задавал похожие вопросы на форуме, и предупреждение появляется, если переменная установлена / установлена без предварительного определения. Но я определил эти переменные с помощью defparameter, но все равно получаю предупреждение.
Одна вещь, которую я заметил, это то, что если я не ссылаюсь на переменные в инструкции format, предупреждение не возникает. Я также пробовал использовать defvar. но он все еще выдает предупреждение. может кто-нибудь помочь мне понять, почему предупреждение выдается при использовании в statment, даже если переменная определена?
(defun main ()
(defvar test-cases 10)
(defvar l 12)
(defvar n 13)
(format t "~a ~a ~a" test-cases l n))
; in: DEFUN MAIN
; (FORMAT T "~a ~a ~a" TEST-CASES L N)
;
; caught WARNING:
; undefined variable: N
;
; caught WARNING:
; undefined variable: TEST-CASES
;
; compilation unit finished
; Undefined variables:
; N TEST-CASES
; caught 2 WARNING conditions
WARNING: redefining COMMON-LISP-USER::MAIN in DEFUN
Комментарии:
1.
DEFVAR
для глобальных переменных, определенных на верхнем уровне. ИспользуетсяLET
для определения локальных переменных. См. Практическую главу Common Lisp 6. Переменные
Ответ №1:
Ниже объясняется, почему у вас ошибка, но обратите внимание, что редко требуется определять глобальные переменные из внутренних функций, большую часть времени вы будете использовать локальную привязку LET
.
Вот сокращенный тестовый пример:
(defun foo () (defvar bar nil) bar)
Во время foo
компиляции bar
не определено (при условии новой среды CL). Вот почему компилятор жалуется. Однако, если вы вызовете foo
, переменная будет объявлена (глобально), а затем будет возвращено ее значение.
Вызов DEFVAR
влияет на глобальную среду только тогда, когда он выполняется, или во время компиляции, когда это форма верхнего уровня:
Однако побочные эффекты во время компиляции, описанные ниже, имеют место только тогда, когда они отображаются как формы верхнего уровня.
…
Побочные эффекты: если
defvar
defparameter
форма или отображается как форма верхнего уровня, компилятор должен распознать, что имя объявлено специальным. Однако он не должен ни оценивать форму начального значения, ни присваивать динамической переменной имя name во время компиляции.
Таким образом, компиляция вызова defvar
внутри тела функции не объявляет символ как специальную переменную.