3

Consider this macro helper function that returns a backquote expression:

(defun make-headers ()
  `(:headers `(("Authorization" . ,(get-auth)))))

This returns the list (:headers `(("Authorization" . ,(get-auth)))), suitable for interpolating into a macro expansion.

Now I want to add an argument which, if not nil, will be used as-is as an additional header; if nil, the original list should be returned. I can't figure out how to interpolate down multiple backquote levels. I thought multiple commas might work, like:

(defun make-headers (content-type)
  `(:headers `(("Authorization" . ,(get-auth))
               ,,@(when content-type (list (cons "Content-Type" content-type))))))

...but this doesn't work as I expected. The best I can do is to awkwardly sort-of duplicate what the original internal backquote was doing:

(defun make-headers (content-type)
  `(:headers (append (list (cons "Authorization" (get-auth)))
                     ,(when content-type (list 'list (list 'cons "Content-Type" content-type)))))))

That's pretty terrible, though. Isn't there a simpler way to interpolate down multiple backquote levels?

For an example simpler than the above, consider this:

(let ((z :z)) `(:foo :bar `(:x :y ,z)))

This evaluates to

(:foo :bar `(:x :y ,z))

So how about:

(let ((z :z)) `(:foo :bar `(:x :y ,,z)))

That produces:

(:foo :bar `(:x :y ,:z))

How can I produce just:

(:foo :bar `(:x :y :z))

1 Answer 1

2

This is maybe as good as it gets:

(let ((z :z)) `(:foo :bar (backquote (:x :y ,z))))

That gives you this:

(:foo :bar (backquote (:x :y :z)))

But maybe someone has a better suggestion. I have a feeling that Elisp doesn't quite have what it takes in this regard. Other Lisp dialects might work better for this.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.