1

Consider this property list:

(defvar *some-variable* (list :foo "fooval" :bar "barval"))

This simple call:

(getf *some-variable* :foo)

yields "fooval" as expected. I define a macro which is supposed to do the same except that I can pass the name of any property to retrieve:

(defmacro my-macro (property-name)
    `(getf *some-variable* :,property-name))

Unfortunately, calling it like this:

(my-macro 'foo)

results in FOO. Why?

9
  • Use MACROEXPAND to debug this. Commented Dec 16, 2017 at 21:49
  • @RainerJoswig: I've already tried that but I'm still clueless. Commented Dec 16, 2017 at 21:54
  • And what did it return? Commented Dec 16, 2017 at 21:54
  • 3
    No-one yet seems to have pointed out that :,x is, essentially, a syntax error. You can't use , to splice things inside the syntax of a symbol: this is as bogus as if you said make-,foo to try and create some symbol. If you want to construct symbols in specific packages you have to do more work than that. Commented Dec 17, 2017 at 14:22
  • 1
    @RainerJoswig Thanks! I should have tried before posting my comment: I think I'd assumed that the conforming interpretation was CLISP's, but I'm actually not sure, perhaps it's just not clear if it is legal or not. What it doesn't do is what OP wanted, obviously. This kind of error tends to come from using 'language in a string' macro systems like (shudder) Jinja2. Commented Dec 17, 2017 at 17:06

1 Answer 1

5

Why don't you just check it out yourself:

(macroexpand-1 '(my-macro 'foo))
; ==> (getf *some-variable* :|| 'foo) ;
T

The documentation for getf says that if you give it a 4th argument it is the value when the key is not found. Since :|| (the empty symbol in the keyword package) doesn't exist it returns the supplied default foo.

So here is a function that does what you want:

(defun get-field (name)
 (getf *some-variable* 
       (intern (symbol-name name) "KEYWORD")))

(defparameter *test* 'foo)
(get-field *test*)
; ==> "fooval"

The only reason to make it a macro is to make it syntax and the main difference between syntax and a function is that the arguments are not evaluated.

(defmacro get-mfield (name)
  `(get-field ',name))

(get-mfield foo)
; ==> "fooval"

(get-mfield *test*)
; ==> nil

You get to come with literals bare, but you loose the feature that *test* is regarded as a variable and not the key :*test*

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.