2

I am a newbie in Lisp. I want to access a particular property from a property list with a string variable like this

(setf sym (list :p1 1))
(setf x "p1")
(getf sym :x)
Rainer Joswig
  • 136,269
  • 10
  • 221
  • 346
emotionull
  • 595
  • 2
  • 8
  • 24

2 Answers2

5

About cl:getf

Let Petit Prince's answer is right that getf is probably the function you want to use here, but note that it can be used for more than just keyword symbols. You can use it for any objects. A property list is just a list of alternating indicators and values, and any object can be an indicator:

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

You can even use strings as indicators:

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

However, that's probably not great practice, since getf compares indicators with eq. That means that using strings as indicators might not be reliable, depending on your use case:

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

For your example

In your case, you're trying to take a string and find the object for a symbol with a name that's string-equal (i.e., with the same characters, but disregarding case). It probably makes more sense to loop over the list and compare indicators with string-equal.

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

And of course, you can wrap that up in a function for abstraction:

(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
Joshua Taylor
  • 84,998
  • 9
  • 154
  • 353
0

The second parameter to getf is a keyword, and you have string. A keyword is a symbol that lives in the package KEYWORD and has usually been uppercased by the reader:

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

So you need to use:

? (getf sym (find-symbol (string-upcase x) "KEYWORD"))
1
uselpa
  • 18,732
  • 2
  • 34
  • 52
  • 1
    The second parameter to **getf** is not necessarily a keyword. It's any object. Keyword symbols are often keywords, but there's also a good usecase for making them *non*-keyword symbols from other packages: it's less likely for indicators to clash. – Joshua Taylor Nov 29 '14 at 15:14
  • 1
    @JoshuaTaylor: since the same numbers and characters don't need to be identical, GETF might not be useful for those... – Rainer Joswig Nov 29 '14 at 16:37
  • @RainerJoswig That's right, and I gave some examples of it in my answer. GETF isn't useful there, but it's still quite useful with non-keyword symbols. – Joshua Taylor Nov 29 '14 at 16:50