反引用扩展列表中的一系列元素

Wil*_*aul 3 lisp clisp common-lisp

假设我有一个结构(其参数多于此处所示):

(defstruct location
  name)
Run Code Online (Sandbox Code Playgroud)

以及使用反引号定义一系列位置的关联列表:

(defparameter *locations* `(
  (ASIA ,(make-location :name "Asia"))
  (AFRICA ,(make-location :name "Africa"))
  )
Run Code Online (Sandbox Code Playgroud)

这工作正常,并正确创建位置结构.问题是,我正计划拥有很多地点,而不仅仅是亲手打包:

(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"))
  )
Run Code Online (Sandbox Code Playgroud)

很多这些额外的位置都有类似的参数,这样我就可以定义一个"生成器函数"来创建它们的列表:

(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)
Run Code Online (Sandbox Code Playgroud)

那么我试着做一些像:

(defparameter *locations* `(
  (ASIA ,(make-location :name "Asia"))
  (AFRICA ,(make-location :name "Africa"))
  ,(generate-locations "LOC" "Location " 1024)
  )
Run Code Online (Sandbox Code Playgroud)

不起作用,因为GENERATE-LOCATIONS返回一个列表,而不是一系列可以添加到列表中的元素.所以我尝试了VALUES-LIST:

(defparameter *locations* `(
  (ASIA ,(make-location :name "Asia"))
  (AFRICA ,(make-location :name "Africa"))
  ,(values-list (generate-locations "LOC" "Location " 1024))
  )
Run Code Online (Sandbox Code Playgroud)

这只会添加第一个生成的位置*LOCATIONS*.我假设这是因为除了第一个之外的所有返回值VALUES-LIST都被忽略.

那么如何正确添加一系列元素*LOCATIONS*呢?应该GENERATE-LOCATIONS是一个宏?如果是这样,它将如何构建?

jbm*_*jbm 8

您需要使用拼接非引号运算符,@.在你的例子中:

(defparameter *locations* `(
  (ASIA ,(make-location :name "Asia"))
  (AFRICA ,(make-location :name "Africa"))
  ,@(generate-locations "LOC" "Location " 1024)
  )
Run Code Online (Sandbox Code Playgroud)

为此,generate-locations应返回一个列表.,@将每个项目拼接到周围列表中,而不是将其作为单个项目插入.