我如何修改此功能以创建动态 plist

how can I modify this function to create a dynamic plist

我想做什么:我想定义一个函数create-record,它接受可变数量的参数(称为键的名称)并生成一个动态plist/named列表。

我只是想让它首先使用动态名称并将 1 分配给所有名称以创建一个列表,如 (:x 0 :y 0 :z 0) 然后我可以修改它以接受键和值(而不是仅仅0 代表所有关键)

我的代码:

(defparameter *test* '('x 'y 'z))
(defun create-record (&rest keys) 
  (let ((count 0))
    (mapcan (lambda (key) (list key count)) keys)))

输出

(create-record-variable *test*)
==>  (('X 'Y 'Z) 0)

预期输出:

(create-record-variable *test*)
==> (:x 0 :y 0 :z 0)

我不确定为什么输出像 (('X 'Y 'Z) 0)

问题不在于函数,而在于调用。 你需要做的是

(create-record 'a :b '#:c)
==> (A 0 :B 0 #:C 0)

或者,如果关键字在列表中,

(defparameter *test* '(:x :y :z))
(apply #'create-record *test*)
==> (:X 0 :Y 0 :Z 0)

如果要将列表作为参数传递,只需删除 &rest

回答评论中的问题,这里是如何创建alist (协会列表):

(defun make-alist (keys values)
  (mapcar #'cons keys values))
(defparameter *my-alist* (make-alist '(:a :b :c) '(1 2 3)))
(assoc :a *my-alist*)
==> (:A . 1)

和一个plist (property list):

(defun make-plist (keys values)
  (mapcan #'list keys values))
(defparameter *my-plist* (make-plist '(:a :b :c) '(1 2 3)))
(getf *my-plist* :b)
==> 2
(defun make-keyword (x)
  "Make out of symbol or string a keyword."
  (values (intern (string x) "KEYWORD")))
;; this is equivalent to alexandria's `alexandria::make-keyword

;; (defun make-keyword (x)
;;   (read-from-string (concatenate 'string ":" (string x))))
;; ;; this doesn't work with "such strings"

(defun create-record (list-of-symbols &key (count 0))
  (mapcan #'(lambda (x) (list (make-keyword x) count)) list-of-symbols))

然后调用它:

(defparameter *test* (list 'x 'y 'z))

(create-record *test*)
;; => (:X 0 :Y 0 :Z 0)

(create-record *test* :count 3)
;; => (:X 3 :Y 3 :Z 3)