假设我有一个结构(它的参数比这里显示的多):
(defstruct location
name)
以及使用反引号定义一系列位置的关联列表:
(defparameter *locations* `(
(ASIA ,(make-location :name "Asia"))
(AFRICA ,(make-location :name "Africa"))
)
这工作正常并正确地创建了位置结构。问题是,我计划有很多位置,而不是手动输入所有位置:
(defparameter *locations* `(
(ASIA ,(make-location :name "Asia"))
(AFRICA ,(make-location :name "Africa"))
(LOC1 ,(make-location :name "Location 1"))
; Lots more...
(LOC1024 ,(make-location :name "Location 1027"))
)
很多这些额外的位置都有相似的参数,这样我就可以定义一个“生成器函数”来创建它们的列表:
(defun generate-locations (symbol name count)
(loop for i from 1 to count collect (list
(read-from-string (format nil "~A~D" symbol i))
(make-location :name name))))
;;; Creates list ((LOC1 #S(LOCATION :NAME "Location 1")) (LOC2 ...
(generate-locations "LOC" "Location " 1024)
然后我尝试做类似的事情:
(defparameter *locations* `(
(ASIA ,(make-location :name "Asia"))
(AFRICA ,(make-location :name "Africa"))
,(generate-locations "LOC" "Location " 1024)
)
不起作用,因为 GENERATE-LOCATIONS
返回一个列表,而不是随后可以添加的系列元素 到一个列表。所以我尝试VALUES-LIST
它:
(defparameter *locations* `(
(ASIA ,(make-location :name "Asia"))
(AFRICA ,(make-location :name "Africa"))
,(values-list (generate-locations "LOC" "Location " 1024))
)
这只会将第一个生成的位置添加到 *LOCATIONS*
。我假设这是因为除了第一个 VALUES-LIST
之外的所有返回值都被忽略了。
那么如何正确地将一系列元素添加到*LOCATIONS*
呢? GENERATE-LOCATIONS
应该是一个宏吗?如果是这样,它将如何构建?
最佳答案
需要使用拼接反引号操作符,@
。在你的例子中:
(defparameter *locations* `(
(ASIA ,(make-location :name "Asia"))
(AFRICA ,(make-location :name "Africa"))
,@(generate-locations "LOC" "Location " 1024)
)
为此,generate-locations
应该返回一个列表。 ,@
会将每个项目拼接到周围的列表中,而不是将其作为单个项目插入。
关于lisp - 反引号扩展列表中的一系列元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18950957/