2015-02-12 5 views

ответ

4

Короткий ответ в том, что вы должны использовать let вместо defparameter ввести переменную. Например:

(defun make_graph (strings) 
    (let ((nodes (make-array 0))) 
    (loop for x in strings do 
      (vector-push-extend (make-instance 'node :data x) nodes)) 
    ;; your code says N here, but I assume that's a typo... 
    nodes)) 

defparameter форма полезна для создания «специальных» переменных, которые несколько похожи на глобальные переменные в других языках программирования. (Есть некоторые различия, например, специальные переменные, введенные defparameter не совсем глобальный --- вместо этого, они с динамической областью видимости, и может быть let связаны, и т.д ...)

В любом случае, let форма вместо этого создаст локальную переменную.

+0

Я бы никогда не использовал 'defparameter' таким образом, но мне любопытно, почему код OP не работал. Я бы подумал, что так будет. – Mars

+0

@ Марс, ответ Райнера Йосвига объясняет это. Короче говоря, переменные, объявленные таким образом, еще не определены во время компиляции, когда компилятор выдает предупреждение. –

4

DEFPARAMETER использовано в toplevel для определения глобальных специальных переменных.

Toplevel:

(defparameter *foo* 42) 

Еще у верхнего уровня, потому что формы внутри PROGN все еще находятся на верхнем уровне (по определению):

(progn 
    (defparameter *foo* 42) 
    (defparameter *bar* 32)) 

Не на верхнем уровне:

(defun baz() 
    (defparameter *foo* 42)) 

Над последнего форма не распознается компилятором как объявление переменной. Но когда вы вызываете (baz) и функция работает, переменная определяется и инициализируется.

Недостаточное использование DEFPARAMETER не будет распознано компилятором, но во время выполнения оно создаст специальную глобальную переменную.

(defun make_graph (strings) 
    (defparameter nodes (make-array 0)) 
    (loop for x in strings do 
     (vector-push-extend (make-instance 'node :data x) nodes)) 
    n) 

Компилятор предупреждает:

;;;*** Warning in MAKE_GRAPH: NODES assumed special 
;;;*** Warning in MAKE_GRAPH: N assumed special 

Таким образом, в приведенном выше коде, компилятор не распознает nodes как определенной переменной, если она не была определена где-то уже. использует из nodes в функции создает предупреждение.

По-прежнему код может работать, поскольку во время выполнения переменная создается и инициализируется, но для каждого вызова функции. Вновь и вновь. Этот компилятор также предполагает, что nodes это просто: какая-то специальная переменная. Тем не менее, я бы не рассчитывал на это для всех компиляторов.

n также не определен нигде.

Примечания:

  • правильный способ ввести локальные лексические переменные, чтобы использовать LET и LET* (и другие обязательные формы)

  • использование DEFPARAMETER в качестве верхнего уровня формы. Это необычно, когда это не форма верхнего уровня. Обычно автор делает ошибку.

Смежные вопросы