2015-05-11 66 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)