【问题标题】:how can I modify this function to create a dynamic plist如何修改此函数以创建动态 plist
【发布时间】:2020-09-07 21:19:35
【问题描述】:

我正在尝试做的事情:我想定义一个函数create-record,它接受可变数量的参数(称为键的名称)并生成一个动态 plist/命名列表。

我只是想让它首先使用动态名称,然后将 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)

【问题讨论】:

    标签: lisp common-lisp


    【解决方案1】:

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

    (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 (association list)

    (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
    

    【讨论】:

    • 谢谢有没有办法我可以修改,所以我可以接受 2 个列表并设置值(所以 id 有 test 包含名称,然后是另一个 var values 包含值所以它会返回 (:x :value1 :y value2 , ...)
    • 另见PAIRLIS
    【解决方案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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-26
      • 1970-01-01
      • 1970-01-01
      • 2018-08-26
      • 1970-01-01
      相关资源
      最近更新 更多