2015-05-11 34 views
0

我在想,如果我可以在Lisp中做这样的事情:LISP连接字符串的变量名称

我需要声明n个变量。因此,他们会N1,N2,N3 ...等

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

这可能吗?

+3

误区四:'(setq(+“N))':1 )'SETQ'不声明变量,它设置它们。 2)它也期待两个论点,而不是一个。 3)'SETQ'是一个特殊的运算符,并且期望一个符号作为它的第一个参数。你提供了一个列表。 4)'+'需要数字作为参数,而不是符号。 第五个错误:'(dotimes(in)(setq(+'ni))':缺少括号 –

+2

实际上,为什么不声明一个* n *长度的向量呢?正如Rainer所说的,你可能会延迟元编程直到你高手正常编程:) –

回答

3

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

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

,这是对排序开始Lisp程序的高级话题。如果你知道你需要ň值单元格,你可能也仅仅使用矢量和阿里夫访问值:

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

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