2013-09-23 2 views
3

Допустим, у меня есть-структура (которая имеет больше параметров, чем показано здесь):кавычка Расширение ряда элементов в списке

(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 быть макросом? И если да, то как это будет структурировано?

ответ

8

Вам необходимо использовать оператор unquote для сращивания, ,@. В вашем примере:

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

Для этого, чтобы работать, generate-locations должен возвращать список. ,@ объединит каждый элемент в окружающий список, вместо того, чтобы вставлять его в отдельный элемент.

+0

@WilliamGaul Вы можете узнать больше о [backquote в HyperSpec] (http://www.lispworks.com/documentation/HyperSpec/Body/02_df.htm). –

+0

@JoshuaTaylor Я не могу поверить, что не видел эту страницу ... должен научиться использовать гиперспец больше: P В любом случае спасибо за ресурс! –

+0

@WilliamGaul Я просто включил его для полноты. Backquote не так сложно найти в спецификации, но некоторые из не-буквенно-цифровых символов могут быть трудно найти, если вы не можете, например, помнить, что они называют символом «#». Например, если вы хотите найти хеш-знак, вы можете, если повезете, в конце концов найти [sharpsign vertical-bar] (http://www.lispworks.com/documentation/lw61/CLHS/Body/02_dhs.htm). Сначала я подумал, что обратный отсчет может быть одним из этих сложных случаев. –

Смежные вопросы