2015-05-11 2 views
0

Мне интересно, могу ли я сделать что-то подобное в Lisp:LISP Перечислите имя переменной со строкой

Мне нужно объявить n переменных. Таким образом, они будут n1, n2, n3 ... и т.д.

(dotimes (i n) (setq (+ 'n i)) 

Возможно ли это?

+3

Четыре ошибки: '(SETQ (+ Ni))': 1) 'SETQ' не объявляет переменные, он их устанавливает. 2) Он также ожидает два аргумента, а не один. 3) 'SETQ' является специальным оператором и ожидает в качестве первого аргумента символ. Вы предоставили список. 4) '+' ожидает числа как аргументы, а не символы. Пятая ошибка: '(dotimes (in) (setq (+ 'ni))': отсутствующие круглые скобки. –

+2

Практически говоря, почему бы не объявить вектор длины * n *? Как показывает Райнер, вы можете приостановить метапрограммирование до тех пор, пока вы освоите нормальное программирование :) –

ответ

3

Rainer Joswig указал в комментарии, что код, который у вас есть, не работает для того, что вы пытаетесь сделать, и объяснил, почему. Если вы пытаетесь использовать , объявите переменными программным способом, вам понадобятся манипуляции с исходным кодом, а это значит, что вам нужен макрос. В этом случае это довольно легко. Мы можем определить макрос с индексированные-вары, которая принимает символ, число, и тело, и расширяющийся к пусть с переменными можно было ожидать, и что оценивает тело в этой сфере:

(defmacro with-indexed-vars ((var n) &body body) 
    "Evalutes BODY within a lexical environment that has X1...XN 
declared as variables by LET. For instance 

    (with-indexed-vars (x 5) 
     (list x1 x2 x3 x4 x5)) 

expands to 

    (LET (X1 X2 X3 X4 X5) 
     (LIST X1 X2 X3 X4 X5)) 

The symbols naming the variables declared by the LET are interned 
into the same package as VAR. All the variables are initialized 
to NIL by LET." 
    (let ((name (symbol-name var))) 
    `(let ,(loop for i from 1 to n 
       collecting (intern (concatenate 'string name (write-to-string i)) 
           (symbol-package var))) 
     ,@body))) 

Затем, мы можем использовать его как это:

(with-indexed-vars (n 4) 
    (setq n3 "three") 
    (setq n4 4) 
    (list n4 n1 n3 n2)) 

;=> (4 NIL "three" NIL) 

Как Шон Allred отмечает в комментарии, это своего рода передовой темой для начала Lisp программирования. Если вы знаете, что вам нужно п значение ячейки, вы можете также просто использовать вектор и Ареф для доступа к значениям:

(let ((ns (make-array 4 :initial-element nil))) 
    (setf (aref ns 2) "three") 
    (setf (aref ns 3) 4) 
    ns) 

;=> #(NIL NIL "three" 4) 
Смежные вопросы