【问题标题】:How to get a property from a plist如何从 plist 中获取属性
【发布时间】:2015-01-27 18:57:00
【问题描述】:

我是 Lisp 的新手。 我想使用这样的字符串变量从属性列表中访问特定属性

(setf sym (list :p1 1))
(setf x "p1")
(getf sym :x)

【问题讨论】:

    标签: lisp common-lisp string-to-symbol


    【解决方案1】:

    关于 cl:getf

    Let Petit Prince 的回答是对的,getf 可能是您要在这里使用的函数,但请注意,它不仅可以用于关键字符号。您可以将它用于任何对象。属性列表只是交替的指标和值的列表,任何对象都可以是指标:

    (let ((plist (list 'a 'b 'c 'd)))
      (getf plist 'c))
    ;=> D
    

    您甚至可以使用字符串作为指标:

    (let* ((name "p1")
           (plist (list name 1)))
      (getf plist name))
    ;=> 1
    

    但是,这可能不是很好的做法,因为 getf 将指标与 eq 进行比较。这意味着使用字符串作为指标可能不可靠,具体取决于您的用例:

    (let ((plist (list "p1" 1)))
      (getf plist "p1"))
    ;=> NIL
    

    举个例子

    在您的情况下,您正在尝试获取一个字符串并查找名称与字符串相等的符号的对象(即,具有相同的字符,但不考虑大小写)。在列表中循环并将指标与string-equal进行比较可能更有意义。

    (let ((plist '(:p1 1 :p2 2)))
      (loop 
         for (indicator value) on plist by #'cddr
         when (string-equal indicator "p1")
         return value))
    ;=> 1
    

    当然,您可以将其封装在一个函数中以进行抽象:

    (defun getf-string-equal (plist indicator)
      (loop
         for (i v) on plist by #'cddr
         when (string-equal i indicator)
         return v))
    

    (getf-string-equal '(:p1 1 :p2 2) "p1")
    ;=> 1
    

    【讨论】:

      【解决方案2】:

      getf 的第二个参数是关键字,你有字符串。关键字是存在于 KEYWORD 包中的符号,通常被读者大写:

      ? (setf sym (list :p1 1))
      (:P1 1)
      ? sym
      (:P1 1)
      

      所以你需要使用:

      ? (getf sym (find-symbol (string-upcase x) "KEYWORD"))
      1
      

      【讨论】:

      • getf 的第二个参数不一定是关键字。它是任何对象。关键字符号通常是关键字,但也有一个很好的用例,可以使它们成为其他包中的 关键字符号:指示符不太可能发生冲突。
      • @JoshuaTaylor:因为相同的数字和字符不需要相同,GETF 可能对那些没有用处......
      • @RainerJoswig 没错,我在回答中举了一些例子。 GETF 在那里用处不大,但对非关键字符号还是很有用的。
      猜你喜欢
      • 1970-01-01
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多