LISP用字符串连接变量名

时间:2015-05-11 17:58:20

标签: lisp

我想知道我是否可以在Lisp中做这样的事情:

我需要声明n个变量。所以他们将是n1,n2,n3 ......等等。

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

有可能吗?

1 个答案:

答案 0 :(得分:3)

Rainer Joswig在评论中指出,你所获得的代码并不适用于你正在尝试做的事情,并解释了原因。如果您尝试以编程方式声明变量,那么您将需要源代码操作,这意味着您需要一个宏。在这种情况下,它很容易。我们可以定义带有符号,数字和正文的宏 with-indexed-vars ,并使用您期望的变量扩展为 let ,以及评估该范围内的正文:

(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)

正如Sean Allred在评论中指出的那样,这是开始Lisp编程的一个高级主题。如果您知道需要 n 值单元格,那么您也可以使用向量和 aref 来访问值:

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

;=> #(NIL NIL "three" 4)