См. Документацию для defvar
в Hyperspec:
Если форма defvar
или defparameter
отображается как форма верхнего уровня, компилятор должен распознать, что имя было объявлено special
.
Это подразумевает (и это похоже на случай с SBCL), что если defvar
появляется как форма не верхнего уровня, то компилятору не нужно распознавать, что имя было объявлено. Так почему же ваши defvar
не компилируются как формы верхнего уровня? См. раздел 3.2.3.1, Обработка форм верхнего уровня (пункт 6) для ответа: let
, окружающий ваш код, вызывает его компиляцию как формы не верхнего уровня.
Так что вам нужно defvar
ваши переменные на верхнем уровне, а затем назначить их позже с setf
внутри let
.
Вот так. Также обычно проще использовать with-open-file
вместо open
и close
.
(defvar var1)
(defvar arr1)
(with-open-file (input "input.lisp" :direction :input)
(setf var1 (read input))
(setf arr1 (make-array var1 :initial-contents (read input))))
(print var1)
(print arr1)
Причиной возникновения этой проблемы является то, что вы помещаете свой код на верхний уровень в файле. Это немного необычная вещь: обычный стиль кодирования на Лиспе состоит в том, чтобы поместить большую часть вашего кода в определения функций, а затем вызывать эти функции, когда вам нужно их запустить.
Например, это был бы более типичный способ написания такого рода кода с кодом инициализации в его собственной функции.
(defvar *var1* nil "Documentation for var1.")
(defvar *arr1* nil "Documentation for arr1.")
(defun init-from-file (file)
"Read *var1* and *arr1* from file."
(with-open-file (input file :direction :input)
(setf *var1* (read input))
(setf *arr1* (make-array *var1* :initial-contents (read input)))))
(when (null *var1*) (init-from-file "input.lisp"))