получение предупреждения «неопределенная переменная», даже если оно определено - PullRequest
1 голос
/ 19 апреля 2019

При выполнении приведенного ниже кода в sbcl repl я получаю предупреждение 'undefined variable' для тестовых случаев переменных, n.Я прошел через аналогичные вопросы на форуме, и появляется предупреждение, если переменная задана / задана без предварительного определения.Но я определил эти переменные, используя defparameter, но все еще получаю предупреждение.

Одна вещь, которую я заметил, - если я не ссылаюсь на переменные в операторе формата, предупреждение не происходит.Я тоже пытался использовать defvar.но это все еще бросает предупреждение.Может ли кто-нибудь помочь мне понять, почему выдается предупреждение при использовании в зачете, даже если переменная определена?

    (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 Ответ

4 голосов
/ 19 апреля 2019

Ниже объясняется , почему возникает ошибка, но обратите внимание, что редко требуется определять глобальные переменные изнутри функций, большую часть времени вы будете использовать локальную привязку с LET.

Вот сокращенный тестовый пример:

(defun foo () (defvar bar nil) bar)

Во время компиляции foo, bar не определено (при условии свежей среды CL).Вот почему компилятор жалуется.Однако, если вы вызовете foo, переменная будет объявлена ​​(глобально), а затем будет возвращено ее значение.

Вызов DEFVAR влияет на глобальныйсреда только тогда, когда она выполняется, или во время компиляции, когда она является формой верхнего уровня:

Однако описанные ниже побочные эффекты времени компиляции имеют место, только когда они появляются как формы верхнего уровня,

...

Побочные эффекты: Если форма defvar или defparameter отображается как форма верхнего уровня, компилятор должен распознать, что имя имеетбыл провозглашен особенным.Однако он не должен ни оценивать форму начального значения, ни назначать динамическую переменную с именем name во время компиляции.

Таким образом, компиляция вызова defvar внутри тела функции не объявляет символ какспециальная переменная.

...