我是 Lisp 的新手。我想使用这样的字符串变量从属性列表中访问特定属性
(setf sym (list :p1 1))
(setf x "p1")
(getf sym :x)
我是 Lisp 的新手。我想使用这样的字符串变量从属性列表中访问特定属性
(setf sym (list :p1 1))
(setf x "p1")
(getf sym :x)
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
to的第二个参数getf
是一个关键字,你有字符串。关键字是存在于 KEYWORD 包中的符号,通常被读者大写:
? (setf sym (list :p1 1))
(:P1 1)
? sym
(:P1 1)
所以你需要使用:
? (getf sym (find-symbol (string-upcase x) "KEYWORD"))
1